Compare commits
644
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a702a8da9 | ||
|
|
8c06c0a78f | ||
|
|
5ad871a34a | ||
|
|
2245918a49 | ||
|
|
107719b4dd | ||
|
|
9534dba818 | ||
|
|
edd0081fe0 | ||
|
|
6093e4c20e | ||
|
|
3826d62dcb | ||
|
|
d97e29099f | ||
|
|
5308c36ab2 | ||
|
|
e2ef47ba81 | ||
|
|
d252575172 | ||
|
|
9a45bc154a | ||
|
|
7de2f95031 | ||
|
|
3898c4ed99 | ||
|
|
a2b2d6c4a8 | ||
|
|
7ee2714490 | ||
|
|
82eacf4ce2 | ||
|
|
80f602303c | ||
|
|
90fa804bb7 | ||
|
|
a5aa5b494a | ||
|
|
aa13010252 | ||
|
|
0b20ba06ed | ||
|
|
109305cfd6 | ||
|
|
db1a109ad7 | ||
|
|
6b70b5ddcd | ||
|
|
fd73d48e0e | ||
|
|
1c38bb7158 | ||
|
|
149ef706dd | ||
|
|
f1c40dd345 | ||
|
|
6225ccfc06 | ||
|
|
34de631b2a | ||
|
|
86f0092622 | ||
|
|
76f3842dad | ||
|
|
d818ebdd9e | ||
|
|
4d90898dd9 | ||
|
|
298b9e01d8 | ||
|
|
d0b08cacd8 | ||
|
|
050c65a520 | ||
|
|
5c2fc1120b | ||
|
|
3d2acbe780 | ||
|
|
bce0e0ea90 | ||
|
|
931102ff26 | ||
|
|
5a3938d12f | ||
|
|
dca1751a63 | ||
|
|
f6ec9af61e | ||
|
|
64f2f84ffa | ||
|
|
5df5e53f11 | ||
|
|
81f4c50574 | ||
|
|
2550d16127 | ||
|
|
f3675681c3 | ||
|
|
28de8dc5b7 | ||
|
|
35e63a9398 | ||
|
|
f23f1cc813 | ||
|
|
b0095154d1 | ||
|
|
79ea9ed314 | ||
|
|
413db0dce1 | ||
|
|
e6745532ce | ||
|
|
59da0f90f8 | ||
|
|
76f0f52ee3 | ||
|
|
73c230f1ca | ||
|
|
ddee72c756 | ||
|
|
6318964374 | ||
|
|
853f1af40d | ||
|
|
d429b2151a | ||
|
|
b223e1a7af | ||
|
|
c806b8911e | ||
|
|
9f30a51925 | ||
|
|
a8b7129269 | ||
|
|
991b0e8ee2 | ||
|
|
e9d1475475 | ||
|
|
bc189554aa | ||
|
|
d0f26ae4cf | ||
|
|
ab6d247ef1 | ||
|
|
fcc82a47e4 | ||
|
|
25e53db96f | ||
|
|
89660d06e5 | ||
|
|
493fd0ad6a | ||
|
|
11422524f3 | ||
|
|
957214ed78 | ||
|
|
f013cca3b8 | ||
|
|
a1cfc0a0ff | ||
|
|
e8b3b3acf3 | ||
|
|
0cfb03be03 | ||
|
|
7d4b93e01e | ||
|
|
2f3793805b | ||
|
|
a310c13d32 | ||
|
|
38a721425d | ||
|
|
dfc34d99c5 | ||
|
|
6c58fd03a4 | ||
|
|
5b9d1286cc | ||
|
|
d9e330802c | ||
|
|
085de8a069 | ||
|
|
5af4c63a3e | ||
|
|
5177365c28 | ||
|
|
4df5ff3004 | ||
|
|
00f6841dc7 | ||
|
|
be8394158f | ||
|
|
fbf62b2a63 | ||
|
|
a047fb947b | ||
|
|
eec3a3d5c3 | ||
|
|
9387de1d1a | ||
|
|
b9c90f128a | ||
|
|
5699efc0f5 | ||
|
|
6ead008bf4 | ||
|
|
34e52839f7 | ||
|
|
bd54e1c60c | ||
|
|
03006522e2 | ||
|
|
7492ae2990 | ||
|
|
6edf890699 | ||
|
|
43fd24f02b | ||
|
|
22ebb81650 | ||
|
|
fd074278f7 | ||
|
|
ad497a66cd | ||
|
|
41275b0e91 | ||
|
|
b82502af1d | ||
|
|
43f2199d46 | ||
|
|
d44541fc9e | ||
|
|
24147a3d84 | ||
|
|
244d879d00 | ||
|
|
f5f67a629e | ||
|
|
aad1d57502 | ||
|
|
cf75c2378f | ||
|
|
3a64c4d582 | ||
|
|
d36376ffcd | ||
|
|
434197c10d | ||
|
|
d4af694c6f | ||
|
|
f245b67036 | ||
|
|
945673c7da | ||
|
|
c25967bd61 | ||
|
|
165fba6b9c | ||
|
|
76209dd899 | ||
|
|
8c8cc53989 | ||
|
|
6f463196ef | ||
|
|
b0e2624343 | ||
|
|
99fda3a7cb | ||
|
|
457039d7ba | ||
|
|
eb4ffbca29 | ||
|
|
c9afe8fcc4 | ||
|
|
d8d6348f67 | ||
|
|
87f7ec5909 | ||
|
|
18583eb6ed | ||
|
|
b9d0219f04 | ||
|
|
d9cb1fc4a9 | ||
|
|
1654be0a85 | ||
|
|
d5944163d6 | ||
|
|
5ca3a48094 | ||
|
|
1fb3d7cd3b | ||
|
|
f827b2dc0d | ||
|
|
0295824923 | ||
|
|
8fee0c946b | ||
|
|
bd13b8a5fe | ||
|
|
743ea95a78 | ||
|
|
2998a0fa35 | ||
|
|
7b0a3989e2 | ||
|
|
06fcb7595a | ||
|
|
bd3c4d4215 | ||
|
|
b969d9edfa | ||
|
|
3ef0fb63a9 | ||
|
|
bf706a9191 | ||
|
|
26be615a80 | ||
|
|
81928eb61a | ||
|
|
126f517520 | ||
|
|
7028496601 | ||
|
|
3a4897c7d2 | ||
|
|
b3f142d715 | ||
|
|
a4e16ca9c7 | ||
|
|
57176dee75 | ||
|
|
f87ba8a3a9 | ||
|
|
8c0b33f902 | ||
|
|
51e927adf7 | ||
|
|
bf4b681506 | ||
|
|
3c88d2cc18 | ||
|
|
c7b5975ac1 | ||
|
|
09901997c1 | ||
|
|
c0f3d851db | ||
|
|
98b6344f03 | ||
|
|
e4b6e4c167 | ||
|
|
d6983e829a | ||
|
|
374a2ad957 | ||
|
|
52fd2d7e75 | ||
|
|
25bb0ade1b | ||
|
|
6d7be80930 | ||
|
|
1f13f6372a | ||
|
|
39fcd84d53 | ||
|
|
d11a83d6e2 | ||
|
|
1978e23cfd | ||
|
|
4cc1a774df | ||
|
|
8a23463328 | ||
|
|
fad2913665 | ||
|
|
c4c27973f3 | ||
|
|
2ae733bd07 | ||
|
|
7665b9f81e | ||
|
|
248322c748 | ||
|
|
523bdd5ec9 | ||
|
|
a8ad00156b | ||
|
|
8f820713fa | ||
|
|
fc7d4b072c | ||
|
|
1801526f65 | ||
|
|
58e37b6a3f | ||
|
|
0bd9cad6ad | ||
|
|
bcc2c893ef | ||
|
|
ac71bbd4b5 | ||
|
|
ae94b30066 | ||
|
|
b3c307affe | ||
|
|
03d3f4229e | ||
|
|
c627b83cc5 | ||
|
|
5469db311d | ||
|
|
75793a36cf | ||
|
|
d68603e4ea | ||
|
|
33e402e7be | ||
|
|
375dce14e6 | ||
|
|
08ae3aee50 | ||
|
|
1ad7d4f1d8 | ||
|
|
f9e8f1f7b7 | ||
|
|
fa0b45625c | ||
|
|
c5459b2614 | ||
|
|
8232773d97 | ||
|
|
53b752ccfe | ||
|
|
07efba364e | ||
|
|
2e52d8ea7a | ||
|
|
a46a7a42a1 | ||
|
|
060a193b48 | ||
|
|
06ee06ae50 | ||
|
|
17a5a9f033 | ||
|
|
e27a754f5f | ||
|
|
61d5ba6a92 | ||
|
|
eff0054b4a | ||
|
|
99cd6c7383 | ||
|
|
5087392162 | ||
|
|
7474a31d95 | ||
|
|
a0197bc9da | ||
|
|
3b2e679aed | ||
|
|
75d69a1ec1 | ||
|
|
930fc66ebf | ||
|
|
04d3d26cb1 | ||
|
|
de940ccff9 | ||
|
|
aedc54cc89 | ||
|
|
de3a776b9a | ||
|
|
5d6cc61d4d | ||
|
|
f32b38cdbc | ||
|
|
f3bfb06dec | ||
|
|
630597746e | ||
|
|
f98036296c | ||
|
|
bf1f867f23 | ||
|
|
8215a85930 | ||
|
|
10a5686955 | ||
|
|
2e3c7a3acf | ||
|
|
06713da67b | ||
|
|
46fb1b6582 | ||
|
|
1b3f98db1e | ||
|
|
a190cdd8f2 | ||
|
|
8e25369001 | ||
|
|
8d90ad816a | ||
|
|
da9e42cb21 | ||
|
|
cbab3ff0d0 | ||
|
|
210b570c89 | ||
|
|
a2203df6a3 | ||
|
|
6a2b369014 | ||
|
|
fda6a6657f | ||
|
|
04565dad00 | ||
|
|
ac0ae06463 | ||
|
|
a8775f757f | ||
|
|
e4f4ed923d | ||
|
|
c7915fa95d | ||
|
|
652b118634 | ||
|
|
f122ff1471 | ||
|
|
f76b90fab9 | ||
|
|
ccd8beae92 | ||
|
|
33f01009d2 | ||
|
|
a0e3a71109 | ||
|
|
f35ecba801 | ||
|
|
0d7f26bd14 | ||
|
|
2f7bdd2640 | ||
|
|
3125e4ddd2 | ||
|
|
c624cb27da | ||
|
|
06adf9a094 | ||
|
|
94ed55ee35 | ||
|
|
95c8603b69 | ||
|
|
9ad2a8272e | ||
|
|
6dc17da00a | ||
|
|
97aa1c6b2c | ||
|
|
084fed8377 | ||
|
|
68d86e4fa1 | ||
|
|
5203373047 | ||
|
|
86de481ba1 | ||
|
|
5d075a97dd | ||
|
|
e89499f5db | ||
|
|
a1f0208767 | ||
|
|
d1964c20ab | ||
|
|
1e035bf2e5 | ||
|
|
f3b87f9cf9 | ||
|
|
d2ea45e1eb | ||
|
|
58ad6b1a40 | ||
|
|
772ef3cd10 | ||
|
|
204dfd52c8 | ||
|
|
244d3452d0 | ||
|
|
e65f8a7150 | ||
|
|
90d6991b9d | ||
|
|
87ca3f203a | ||
|
|
3f3a20e178 | ||
|
|
ce1a19fdbe | ||
|
|
26ac92a6b1 | ||
|
|
1c7dd0a533 | ||
|
|
ceb29d76b2 | ||
|
|
6efb354cce | ||
|
|
8ae242a6ed | ||
|
|
5f0f92fd15 | ||
|
|
e521fa3554 | ||
|
|
b8f73cf21f | ||
|
|
d068cddbaf | ||
|
|
99422835ab | ||
|
|
68263360c7 | ||
|
|
34f5ddab0f | ||
|
|
0cc4630fc6 | ||
|
|
ee57c79784 | ||
|
|
7e41b8df27 | ||
|
|
79c1d7bafa | ||
|
|
652b2fee86 | ||
|
|
dfb871c26a | ||
|
|
99f74acb94 | ||
|
|
83f7682606 | ||
|
|
c4a07f3098 | ||
|
|
c9451f4f35 | ||
|
|
dff4922783 | ||
|
|
c05b666f3c | ||
|
|
9905024f08 | ||
|
|
b0cb457287 | ||
|
|
d4946c1c08 | ||
|
|
1d745b5cbd | ||
|
|
c99785f266 | ||
|
|
9ecdec3f45 | ||
|
|
866f45bd95 | ||
|
|
320a79dbff | ||
|
|
1e0b6f1aad | ||
|
|
251ad6727a | ||
|
|
1b1f56d183 | ||
|
|
7dc05a45ac | ||
|
|
7257bab289 | ||
|
|
48a76c2d0d | ||
|
|
d78c83b236 | ||
|
|
d9b0415047 | ||
|
|
af2e3de96d | ||
|
|
1c142cb170 | ||
|
|
d5dae7d444 | ||
|
|
85816be967 | ||
|
|
e66d658955 | ||
|
|
1916fded95 | ||
|
|
8cc8f4c49c | ||
|
|
1a3bf16729 | ||
|
|
5304b533fc | ||
|
|
0156d47d97 | ||
|
|
b04ac6cdba | ||
|
|
f43e4200da | ||
|
|
2ba7aef2b1 | ||
|
|
7a1932cab4 | ||
|
|
59f189229c | ||
|
|
29af7a1d29 | ||
|
|
3d9ddc53e6 | ||
|
|
1a34feda65 | ||
|
|
d8c1081578 | ||
|
|
1085a1da62 | ||
|
|
576db8e0e1 | ||
|
|
fe9dc4a28d | ||
|
|
d2aaae2340 | ||
|
|
84e40cbc2c | ||
|
|
42672a9ae2 | ||
|
|
2dd2173553 | ||
|
|
fcd5400cda | ||
|
|
23b69bb7a7 | ||
|
|
c31b0945d8 | ||
|
|
c71a4ac4e8 | ||
|
|
38c7ca64cb | ||
|
|
bc187fe7b3 | ||
|
|
548c0db0ae | ||
|
|
3ecd1307b0 | ||
|
|
b51661b790 | ||
|
|
02d6e41ce3 | ||
|
|
f884aed25e | ||
|
|
f2dee1a470 | ||
|
|
d5d806760f | ||
|
|
efe2a8f789 | ||
|
|
69bbed999f | ||
|
|
5b7d4184f0 | ||
|
|
422b7ed5ef | ||
|
|
66a2b916f2 | ||
|
|
27ac253098 | ||
|
|
1839b24b90 | ||
|
|
a60ebb6210 | ||
|
|
4dba4f3c02 | ||
|
|
6727af2f35 | ||
|
|
5bcf334bc5 | ||
|
|
ef49bd685e | ||
|
|
092562fb94 | ||
|
|
44e2983803 | ||
|
|
2e848da1a8 | ||
|
|
22ae4ecb23 | ||
|
|
1642ac2394 | ||
|
|
be8aa93cca | ||
|
|
fc7ba85639 | ||
|
|
11d1dd6419 | ||
|
|
e8bd7270e9 | ||
|
|
99e2afa81b | ||
|
|
676792d07d | ||
|
|
0bec2bcd1e | ||
|
|
25328048aa | ||
|
|
e51d2137cf | ||
|
|
5695677873 | ||
|
|
9d86f582ac | ||
|
|
97b0558f71 | ||
|
|
e825be1c79 | ||
|
|
88252c3dfc | ||
|
|
02997b593f | ||
|
|
9de81a0b14 | ||
|
|
ab13182091 | ||
|
|
e75e4580ae | ||
|
|
b7f031d199 | ||
|
|
808d27be2d | ||
|
|
dcf8751ff7 | ||
|
|
ec6e3d80ee | ||
|
|
5a9badf683 | ||
|
|
dd11dcef93 | ||
|
|
e9851957f0 | ||
|
|
57cfbb3770 | ||
|
|
da2590819d | ||
|
|
d74d93a522 | ||
|
|
b3eadcc990 | ||
|
|
f4d4405c20 | ||
|
|
1ebec0e2e5 | ||
|
|
4433347ff3 | ||
|
|
08c539ba51 | ||
|
|
4e538dd138 | ||
|
|
66373ccab2 | ||
|
|
9c82c0700d | ||
|
|
a480e50c16 | ||
|
|
4391bf4f70 | ||
|
|
18f46cb527 | ||
|
|
32b89adc04 | ||
|
|
5a213fcad9 | ||
|
|
d6f1d1bb3c | ||
|
|
c8c0d0e804 | ||
|
|
aeddf2a860 | ||
|
|
b876a5f7bd | ||
|
|
af8949c291 | ||
|
|
e3da38df7c | ||
|
|
a16079e38d | ||
|
|
e13b0fac63 | ||
|
|
26190350c4 | ||
|
|
7598cc62d3 | ||
|
|
b3211fa8c2 | ||
|
|
8dcc909b6e | ||
|
|
fafaf2c490 | ||
|
|
11e2f19503 | ||
|
|
d67bd0eff2 | ||
|
|
43bbea9a7c | ||
|
|
dc366c53a7 | ||
|
|
fe1ede26be | ||
|
|
aca799b28c | ||
|
|
1017a0af1d | ||
|
|
ff25484a34 | ||
|
|
af922920ab | ||
|
|
919a3f1b91 | ||
|
|
1ec8e63e9e | ||
|
|
96c76a059a | ||
|
|
608701aea7 | ||
|
|
142d44a01f | ||
|
|
83c0f537ce | ||
|
|
aeab25b7fe | ||
|
|
ef255c6a5c | ||
|
|
474ebed0ee | ||
|
|
6e55604dc3 | ||
|
|
2dfdfefb1a | ||
|
|
48f78cf80a | ||
|
|
69cc28dd4b | ||
|
|
adb8bcf791 | ||
|
|
bd22d30674 | ||
|
|
afbf1cc33f | ||
|
|
485df59c5b | ||
|
|
43308b326d | ||
|
|
6c9708c700 | ||
|
|
4a962aa75a | ||
|
|
e786158071 | ||
|
|
ea5a767948 | ||
|
|
bde65a6c57 | ||
|
|
94c0a436b5 | ||
|
|
bddf1adeba | ||
|
|
9406a577c2 | ||
|
|
40344726e1 | ||
|
|
08ffea23b7 | ||
|
|
f1ddaa8051 | ||
|
|
7ae62c1060 | ||
|
|
7c51046d8a | ||
|
|
df6d75e2c5 | ||
|
|
3c88d9666d | ||
|
|
ee74025f38 | ||
|
|
d49c7d47a2 | ||
|
|
8f18e9bbbc | ||
|
|
be96a3785b | ||
|
|
f3aeb5ec9f | ||
|
|
71ea61e7a6 | ||
|
|
c6c73e5e59 | ||
|
|
ae242f8480 | ||
|
|
351a17f68d | ||
|
|
1c4f7cb339 | ||
|
|
2713af189f | ||
|
|
be62d1a915 | ||
|
|
68d71a6767 | ||
|
|
46c88ad1bf | ||
|
|
917151123f | ||
|
|
b9e9d6a787 | ||
|
|
db20077c37 | ||
|
|
ec3d027f90 | ||
|
|
50678085c9 | ||
|
|
5af4785ba1 | ||
|
|
f59d42d5d3 | ||
|
|
fc7ae1ee96 | ||
|
|
2699bb9a44 | ||
|
|
212f5b4082 | ||
|
|
9591f48077 | ||
|
|
0a8494a0f2 | ||
|
|
39f2a4ab71 | ||
|
|
39aa09ca36 | ||
|
|
45c5a2ae78 | ||
|
|
a1c612f833 | ||
|
|
bc39bb32d4 | ||
|
|
884308ecb5 | ||
|
|
2d7f232c3d | ||
|
|
afa65d9ead | ||
|
|
605c88a029 | ||
|
|
09994d1730 | ||
|
|
bb9c99ebf6 | ||
|
|
d4819886a6 | ||
|
|
23445123a2 | ||
|
|
773bb43b41 | ||
|
|
493dddde02 | ||
|
|
2e5704c6b4 | ||
|
|
be6c843bba | ||
|
|
064d677fdc | ||
|
|
084ab782da | ||
|
|
1a10a1ef75 | ||
|
|
acc77e4e6c | ||
|
|
2c0ff9be60 | ||
|
|
b9f5946cf0 | ||
|
|
c403968fa8 | ||
|
|
14baef425e | ||
|
|
8da532da93 | ||
|
|
facf701897 | ||
|
|
f9fe9ea5d6 | ||
|
|
f5a80c3007 | ||
|
|
7cff37e707 | ||
|
|
4e8c6b3fc4 | ||
|
|
82282c1c75 | ||
|
|
d7379f29da | ||
|
|
000159226d | ||
|
|
4ebdb8d24b | ||
|
|
fc2df08e15 | ||
|
|
aaa83dc19a | ||
|
|
adff0d5da0 | ||
|
|
285d6931bc | ||
|
|
114b687c5c | ||
|
|
a26ade3988 | ||
|
|
94e2983310 | ||
|
|
fb2f5f6756 | ||
|
|
d7b818cba2 | ||
|
|
8d885d14ed | ||
|
|
39e0023a5f | ||
|
|
84faac0cd6 | ||
|
|
1bce639d35 | ||
|
|
f2061610b9 | ||
|
|
8716f9b41a | ||
|
|
a24c817bb7 | ||
|
|
47997e0056 | ||
|
|
70fd7bea99 | ||
|
|
52565375b3 | ||
|
|
2c327d9eee | ||
|
|
caeb710444 | ||
|
|
0b0b101184 | ||
|
|
f5b4a0788e | ||
|
|
1aa338fe3e | ||
|
|
5615d8d870 | ||
|
|
9711ccd914 | ||
|
|
fbc2b845ad | ||
|
|
39ecca0989 | ||
|
|
f19b6afd85 | ||
|
|
dca347398d | ||
|
|
de6341bd87 | ||
|
|
5cb9dbb87a | ||
|
|
dddc5181e7 | ||
|
|
3b78fa2d5d | ||
|
|
2a64f5e3ce | ||
|
|
8f5b53e3ce | ||
|
|
605f5decb3 | ||
|
|
d00e128920 | ||
|
|
226c1c53c0 | ||
|
|
001b874903 | ||
|
|
cc523ea356 | ||
|
|
5dc2b7b1d5 | ||
|
|
cd84e78b27 | ||
|
|
dedaa24972 | ||
|
|
1b0c4e5d1f | ||
|
|
b7e3fc5f73 | ||
|
|
9b9ec09788 | ||
|
|
bd7ceb0b73 | ||
|
|
9638c0dd83 | ||
|
|
60f40544bb | ||
|
|
066fb7178d | ||
|
|
cd762e5e8c | ||
|
|
f990d68cee | ||
|
|
88f14b39a7 | ||
|
|
eda64584d7 | ||
|
|
2f2a2dced6 | ||
|
|
38a2ea2fdf | ||
|
|
43bad9a608 | ||
|
|
be5f3086ce | ||
|
|
663f12d5e6 | ||
|
|
6e758d721d | ||
|
|
4c98b04ab7 | ||
|
|
f846645989 | ||
|
|
6bc79b590c | ||
|
|
2ad7e870d8 | ||
|
|
87636669ae | ||
|
|
8d627f1329 | ||
|
|
c51cc4703b | ||
|
|
a1124c9e1f | ||
|
|
20e245cb05 | ||
|
|
5c8e165080 | ||
|
|
afe088a9e8 | ||
|
|
162f31baa2 | ||
|
|
28a50df746 | ||
|
|
5a0d600322 | ||
|
|
38c1945ce4 | ||
|
|
392fa21f1e | ||
|
|
fa99b5415d | ||
|
|
c52d16da6d | ||
|
|
3f62cd9271 | ||
|
|
3dd282e11b | ||
|
|
95349e6e2e | ||
|
|
dcc40b0a63 | ||
|
|
dc0d9a8dce | ||
|
|
021b01f0bd | ||
|
|
9ab023cc6c | ||
|
|
b54061fc3f | ||
|
|
c12fe28b2d |
No files matched your search
@@ -0,0 +1,20 @@
|
|||||||
|
* text=auto
|
||||||
|
|
||||||
|
*.html text eol=lf
|
||||||
|
*.java text eol=lf
|
||||||
|
*.js text eol=lf
|
||||||
|
*.json text eol=lf
|
||||||
|
*.jsp text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
*.properties text eol=lf
|
||||||
|
*.svg text auto
|
||||||
|
*.xml text eol=lf
|
||||||
|
*.xsl text eol=lf
|
||||||
|
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.gif binary
|
||||||
|
*.ttf binary
|
||||||
|
*.eot binary
|
||||||
|
*.otf binary
|
||||||
|
*.woff binary
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
language: java
|
language: java
|
||||||
|
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.m2
|
- $HOME/.m2
|
||||||
@@ -7,4 +10,10 @@ cache:
|
|||||||
before_cache:
|
before_cache:
|
||||||
- rm -rf $HOME/.m2/repository/org/keycloak
|
- rm -rf $HOME/.m2/repository/org/keycloak
|
||||||
|
|
||||||
|
install: mvn install -Pdistribution -DskipTests=true -B -V
|
||||||
|
|
||||||
|
script:
|
||||||
|
- mvn test -B
|
||||||
|
- mvn -file testsuite/integration-arquillian test -B
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -43,6 +44,7 @@ public class BrokeredIdentityContext {
|
|||||||
private IdentityProviderModel idpConfig;
|
private IdentityProviderModel idpConfig;
|
||||||
private IdentityProvider idp;
|
private IdentityProvider idp;
|
||||||
private Map<String, Object> contextData = new HashMap<>();
|
private Map<String, Object> contextData = new HashMap<>();
|
||||||
|
private ClientSessionModel clientSession;
|
||||||
|
|
||||||
public BrokeredIdentityContext(String id) {
|
public BrokeredIdentityContext(String id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
@@ -166,6 +168,14 @@ public class BrokeredIdentityContext {
|
|||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClientSessionModel getClientSession() {
|
||||||
|
return clientSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSession(ClientSessionModel clientSession) {
|
||||||
|
this.clientSession = clientSession;
|
||||||
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
int i = name.lastIndexOf(' ');
|
int i = name.lastIndexOf(' ');
|
||||||
|
|||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class HardcodedAttributeMapper extends AbstractIdentityProviderMapper {
|
||||||
|
public static final String ATTRIBUTE = "attribute";
|
||||||
|
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||||
|
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ProviderConfigProperty property;
|
||||||
|
property = new ProviderConfigProperty();
|
||||||
|
property.setName(ATTRIBUTE);
|
||||||
|
property.setLabel("User Attribute");
|
||||||
|
property.setHelpText("Name of user attribute you want to hardcode");
|
||||||
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
|
configProperties.add(property);
|
||||||
|
property = new ProviderConfigProperty();
|
||||||
|
property.setName(ATTRIBUTE_VALUE);
|
||||||
|
property.setLabel("User Attribute Value");
|
||||||
|
property.setHelpText("Value you want to hardcode");
|
||||||
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
|
configProperties.add(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return configProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Attribute Importer";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Hardcoded Attribute";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
|
||||||
|
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "hardcoded-attribute-idp-mapper";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getCompatibleProviders() {
|
||||||
|
return COMPATIBLE_PROVIDERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
|
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
|
||||||
|
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
|
||||||
|
user.setSingleAttribute(attribute, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
|
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
|
||||||
|
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
|
||||||
|
user.setSingleAttribute(attribute, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "When user is imported from provider, hardcode a value to a specific user attribute.";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,15 +27,15 @@ public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
|
|||||||
property = new ProviderConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ROLE);
|
property.setName(ROLE);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.ROLE_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String[] parseRole(String role) {
|
public static String[] parseRole(String role) {
|
||||||
int scopeIndex = role.indexOf('.');
|
int scopeIndex = role.lastIndexOf('.');
|
||||||
if (scopeIndex > -1) {
|
if (scopeIndex > -1) {
|
||||||
String appName = role.substring(0, scopeIndex);
|
String appName = role.substring(0, scopeIndex);
|
||||||
role = role.substring(scopeIndex + 1);
|
role = role.substring(scopeIndex + 1);
|
||||||
|
|||||||
Executable
+87
@@ -0,0 +1,87 @@
|
|||||||
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProviderMapper {
|
||||||
|
public static final String ATTRIBUTE = "attribute";
|
||||||
|
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||||
|
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ProviderConfigProperty property;
|
||||||
|
property = new ProviderConfigProperty();
|
||||||
|
property.setName(ATTRIBUTE);
|
||||||
|
property.setLabel("User Session Attribute");
|
||||||
|
property.setHelpText("Name of user session attribute you want to hardcode");
|
||||||
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
|
configProperties.add(property);
|
||||||
|
property = new ProviderConfigProperty();
|
||||||
|
property.setName(ATTRIBUTE_VALUE);
|
||||||
|
property.setLabel("User Session Attribute Value");
|
||||||
|
property.setHelpText("Value you want to hardcode");
|
||||||
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
|
configProperties.add(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
|
return configProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayCategory() {
|
||||||
|
return "Attribute Importer";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisplayType() {
|
||||||
|
return "Hardcoded User Session Attribute";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
|
||||||
|
|
||||||
|
|
||||||
|
public static final String PROVIDER_ID = "hardcoded-user-session-attribute-idp-mapper";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return PROVIDER_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getCompatibleProviders() {
|
||||||
|
return COMPATIBLE_PROVIDERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
|
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
|
||||||
|
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
|
||||||
|
context.getClientSession().setUserSessionNote(attribute, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
|
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
|
||||||
|
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
|
||||||
|
context.getClientSession().setUserSessionNote(attribute, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelpText() {
|
||||||
|
return "When user is imported from provider, hardcode a value to a specific user session attribute.";
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -1 +1,3 @@
|
|||||||
org.keycloak.broker.provider.HardcodedRoleMapper
|
org.keycloak.broker.provider.HardcodedRoleMapper
|
||||||
|
org.keycloak.broker.provider.HardcodedAttributeMapper
|
||||||
|
org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -289,10 +289,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
|||||||
}
|
}
|
||||||
JsonWebToken token = jws.readJsonContent(JsonWebToken.class);
|
JsonWebToken token = jws.readJsonContent(JsonWebToken.class);
|
||||||
|
|
||||||
String aud = token.getAudience();
|
|
||||||
String iss = token.getIssuer();
|
String iss = token.getIssuer();
|
||||||
|
|
||||||
if (aud != null && !aud.equals(getConfig().getClientId())) {
|
if (!token.hasAudience(getConfig().getClientId())) {
|
||||||
throw new IdentityBrokerException("Wrong audience from token.");
|
throw new IdentityBrokerException("Wrong audience from token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -110,7 +110,7 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
|
|||||||
|
|
||||||
String value = getJsonValue(mapperModel, context);
|
String value = getJsonValue(mapperModel, context);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
user.setAttribute(attribute, value);
|
user.setSingleAttribute(attribute, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public class ClaimToRoleMapper extends AbstractClaimMapper {
|
|||||||
property = new ProviderConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(HardcodedRoleMapper.ROLE);
|
property.setName(HardcodedRoleMapper.ROLE);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role to grant to user if claim is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role to grant to user if claim is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.ROLE_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -40,8 +40,8 @@ public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
|
|||||||
property = new ProviderConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(HardcodedRoleMapper.ROLE);
|
property.setName(HardcodedRoleMapper.ROLE);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role to grant to user if external role is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role to grant to user if external role is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.ROLE_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,14 @@ package org.keycloak.broker.oidc.mappers;
|
|||||||
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
|
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
|
||||||
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
|
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
|
||||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.provider.ProviderConfigProperty;
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,7 +74,7 @@ public class UserAttributeMapper extends AbstractClaimMapper {
|
|||||||
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
||||||
Object value = getClaimValue(mapperModel, context);
|
Object value = getClaimValue(mapperModel, context);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
user.setAttribute(attribute, value.toString());
|
user.setSingleAttribute(attribute, value.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +82,9 @@ public class UserAttributeMapper extends AbstractClaimMapper {
|
|||||||
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
||||||
Object value = getClaimValue(mapperModel, context);
|
Object value = getClaimValue(mapperModel, context);
|
||||||
String current = user.getAttribute(attribute);
|
String current = user.getFirstAttribute(attribute);
|
||||||
if (value != null && !value.equals(current)) {
|
if (value != null && !value.equals(current)) {
|
||||||
user.setAttribute(attribute, value.toString());
|
user.setSingleAttribute(attribute, value.toString());
|
||||||
} else if (value == null) {
|
} else if (value == null) {
|
||||||
user.removeAttribute(attribute);
|
user.removeAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -286,7 +286,8 @@ public class SAMLEndpoint {
|
|||||||
|
|
||||||
identity.setUsername(subjectNameID.getValue());
|
identity.setUsername(subjectNameID.getValue());
|
||||||
|
|
||||||
if (subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
|
//SAML Spec 2.2.2 Format is optional
|
||||||
|
if (subjectNameID.getFormat() != null && subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
|
||||||
identity.setEmail(subjectNameID.getValue());
|
identity.setEmail(subjectNameID.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -59,8 +59,8 @@ public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
|
|||||||
property = new ProviderConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(HardcodedRoleMapper.ROLE);
|
property.setName(HardcodedRoleMapper.ROLE);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ProviderConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.ROLE_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,14 @@ package org.keycloak.broker.saml.mappers;
|
|||||||
|
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
|
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
|
||||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
|
||||||
import org.keycloak.broker.saml.SAMLEndpoint;
|
import org.keycloak.broker.saml.SAMLEndpoint;
|
||||||
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
|
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.IdentityProviderMapperModel;
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.provider.ProviderConfigProperty;
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
@@ -87,7 +84,7 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper {
|
|||||||
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
||||||
Object value = getAttribute(mapperModel, context);
|
Object value = getAttribute(mapperModel, context);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
user.setAttribute(attribute, value.toString());
|
user.setSingleAttribute(attribute, value.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +98,7 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper {
|
|||||||
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
|
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
|
||||||
AttributeType attr = choice.getAttribute();
|
AttributeType attr = choice.getAttribute();
|
||||||
if (name != null && !name.equals(attr.getName())) continue;
|
if (name != null && !name.equals(attr.getName())) continue;
|
||||||
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
|
if (friendly != null && !friendly.equals(attr.getFriendlyName())) continue;
|
||||||
|
|
||||||
List<Object> attributeValue = attr.getAttributeValue();
|
List<Object> attributeValue = attr.getAttributeValue();
|
||||||
if (attributeValue == null || attributeValue.isEmpty()) return null;
|
if (attributeValue == null || attributeValue.isEmpty()) return null;
|
||||||
@@ -115,9 +112,9 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper {
|
|||||||
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
|
||||||
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
|
||||||
Object value = getAttribute(mapperModel, context);
|
Object value = getAttribute(mapperModel, context);
|
||||||
String current = user.getAttribute(attribute);
|
String current = user.getFirstAttribute(attribute);
|
||||||
if (value != null && !value.equals(current)) {
|
if (value != null && !value.equals(current)) {
|
||||||
user.setAttribute(attribute, value.toString());
|
user.setSingleAttribute(attribute, value.toString());
|
||||||
} else if (value == null) {
|
} else if (value == null) {
|
||||||
user.removeAttribute(attribute);
|
user.removeAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+1
-12
@@ -90,18 +90,7 @@ public class DefaultFileConnectionProviderFactory implements FileConnectionProvi
|
|||||||
ImportUtils.importFromStream(session, JsonSerialization.mapper, fis, Strategy.IGNORE_EXISTING);
|
ImportUtils.importFromStream(session, JsonSerialization.mapper, fis, Strategy.IGNORE_EXISTING);
|
||||||
session.realms().getMigrationModel().setStoredVersion(model.getModelVersion());
|
session.realms().getMigrationModel().setStoredVersion(model.getModelVersion());
|
||||||
|
|
||||||
List<RealmRepresentation> realmReps = new ArrayList<RealmRepresentation>();
|
ImportUtils.importRealms(session, model.getRealms(), Strategy.IGNORE_EXISTING);
|
||||||
for (RealmRepresentation realmRep : model.getRealms()) {
|
|
||||||
if (Config.getAdminRealm().equals(realmRep.getRealm())) {
|
|
||||||
realmReps.add(0, realmRep);
|
|
||||||
} else {
|
|
||||||
realmReps.add(realmRep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (RealmRepresentation realmRep : realmReps) {
|
|
||||||
ImportUtils.importRealm(session, realmRep, Strategy.IGNORE_EXISTING);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
logger.error("Unable to read model file " + kcdata.getAbsolutePath(), ioe);
|
logger.error("Unable to read model file " + kcdata.getAbsolutePath(), ioe);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+15
-8
@@ -46,26 +46,26 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
|
|||||||
private static final String CHANGELOG = "META-INF/jpa-changelog-master.xml";
|
private static final String CHANGELOG = "META-INF/jpa-changelog-master.xml";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentVersionSql() {
|
public String getCurrentVersionSql(String defaultSchema) {
|
||||||
return "SELECT ID from DATABASECHANGELOG ORDER BY DATEEXECUTED DESC LIMIT 1";
|
return "SELECT ID from " + getTable("DATABASECHANGELOG", defaultSchema) + " ORDER BY DATEEXECUTED DESC LIMIT 1";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(KeycloakSession session, Connection connection) {
|
public void update(KeycloakSession session, Connection connection, String defaultSchema) {
|
||||||
logger.debug("Starting database update");
|
logger.debug("Starting database update");
|
||||||
|
|
||||||
// Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
|
// Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
|
||||||
ThreadLocalSessionContext.setCurrentSession(session);
|
ThreadLocalSessionContext.setCurrentSession(session);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Liquibase liquibase = getLiquibase(connection);
|
Liquibase liquibase = getLiquibase(connection, defaultSchema);
|
||||||
|
|
||||||
List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
|
List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
|
||||||
if (!changeSets.isEmpty()) {
|
if (!changeSets.isEmpty()) {
|
||||||
if (changeSets.get(0).getId().equals(FIRST_VERSION)) {
|
if (changeSets.get(0).getId().equals(FIRST_VERSION)) {
|
||||||
Statement statement = connection.createStatement();
|
Statement statement = connection.createStatement();
|
||||||
try {
|
try {
|
||||||
statement.executeQuery("SELECT id FROM REALM");
|
statement.executeQuery("SELECT id FROM " + getTable("REALM", defaultSchema));
|
||||||
|
|
||||||
logger.infov("Updating database from {0} to {1}", FIRST_VERSION, changeSets.get(changeSets.size() - 1).getId());
|
logger.infov("Updating database from {0} to {1}", FIRST_VERSION, changeSets.get(changeSets.size() - 1).getId());
|
||||||
liquibase.markNextChangeSetRan(null);
|
liquibase.markNextChangeSetRan(null);
|
||||||
@@ -93,9 +93,9 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validate(Connection connection) {
|
public void validate(Connection connection, String defaultSchema) {
|
||||||
try {
|
try {
|
||||||
Liquibase liquibase = getLiquibase(connection);
|
Liquibase liquibase = getLiquibase(connection, defaultSchema);
|
||||||
|
|
||||||
liquibase.validate();
|
liquibase.validate();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -103,7 +103,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Liquibase getLiquibase(Connection connection) throws Exception {
|
private Liquibase getLiquibase(Connection connection, String defaultSchema) throws Exception {
|
||||||
ServiceLocator sl = ServiceLocator.getInstance();
|
ServiceLocator sl = ServiceLocator.getInstance();
|
||||||
|
|
||||||
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
|
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
|
||||||
@@ -125,6 +125,9 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
|
|||||||
|
|
||||||
LogFactory.setInstance(new LogWrapper());
|
LogFactory.setInstance(new LogWrapper());
|
||||||
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
|
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
|
||||||
|
if (defaultSchema != null) {
|
||||||
|
database.setDefaultSchemaName(defaultSchema);
|
||||||
|
}
|
||||||
return new Liquibase(CHANGELOG, new ClassLoaderResourceAccessor(getClass().getClassLoader()), database);
|
return new Liquibase(CHANGELOG, new ClassLoaderResourceAccessor(getClass().getClassLoader()), database);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,4 +231,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getTable(String table, String defaultSchema) {
|
||||||
|
return defaultSchema != null ? defaultSchema + "." + table : table;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-1
@@ -12,6 +12,7 @@ import liquibase.statement.SqlStatement;
|
|||||||
import liquibase.statement.core.UpdateStatement;
|
import liquibase.statement.core.UpdateStatement;
|
||||||
import liquibase.structure.core.Schema;
|
import liquibase.structure.core.Schema;
|
||||||
import liquibase.structure.core.Table;
|
import liquibase.structure.core.Table;
|
||||||
|
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
@@ -36,7 +37,7 @@ public class AddRealmCodeSecret implements CustomSqlChange {
|
|||||||
|
|
||||||
String correctedTableName = database.correctObjectName("REALM", Table.class);
|
String correctedTableName = database.correctObjectName("REALM", Table.class);
|
||||||
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
|
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
|
||||||
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM REALM WHERE CODE_SECRET IS NULL");
|
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM " + LiquibaseJpaUpdaterProvider.getTable(correctedTableName, database.getDefaultSchemaName()) + " WHERE CODE_SECRET IS NULL");
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
String id = resultSet.getString(1);
|
String id = resultSet.getString(1);
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -16,6 +16,7 @@ import liquibase.snapshot.SnapshotGeneratorFactory;
|
|||||||
import liquibase.statement.SqlStatement;
|
import liquibase.statement.SqlStatement;
|
||||||
import liquibase.structure.core.Table;
|
import liquibase.structure.core.Table;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
|
||||||
import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext;
|
import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.services.DefaultKeycloakSessionFactory;
|
import org.keycloak.services.DefaultKeycloakSessionFactory;
|
||||||
@@ -88,7 +89,7 @@ public abstract class CustomKeycloakTask implements CustomSqlChange {
|
|||||||
try {
|
try {
|
||||||
String correctedTableName = database.correctObjectName("REALM", Table.class);
|
String correctedTableName = database.correctObjectName("REALM", Table.class);
|
||||||
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
|
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
|
||||||
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM REALM");
|
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM " + getTableName(correctedTableName));
|
||||||
try {
|
try {
|
||||||
return (resultSet.next());
|
return (resultSet.next());
|
||||||
} finally {
|
} finally {
|
||||||
@@ -108,4 +109,9 @@ public abstract class CustomKeycloakTask implements CustomSqlChange {
|
|||||||
protected abstract void generateStatementsImpl() throws CustomChangeException;
|
protected abstract void generateStatementsImpl() throws CustomChangeException;
|
||||||
|
|
||||||
protected abstract String getTaskId();
|
protected abstract String getTaskId();
|
||||||
|
|
||||||
|
// get Table name for sql selects
|
||||||
|
protected String getTableName(String tableName) {
|
||||||
|
return LiquibaseJpaUpdaterProvider.getTable(tableName, database.getDefaultSchemaName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+13
-8
@@ -11,6 +11,7 @@ import liquibase.statement.core.InsertStatement;
|
|||||||
import liquibase.statement.core.UpdateStatement;
|
import liquibase.statement.core.UpdateStatement;
|
||||||
import liquibase.structure.core.Table;
|
import liquibase.structure.core.Table;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
|
||||||
import org.keycloak.migration.MigrationProvider;
|
import org.keycloak.migration.MigrationProvider;
|
||||||
import org.keycloak.models.AdminRoles;
|
import org.keycloak.models.AdminRoles;
|
||||||
import org.keycloak.models.ClaimMask;
|
import org.keycloak.models.ClaimMask;
|
||||||
@@ -49,7 +50,10 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
String identityProviderTableName = database.correctObjectName("IDENTITY_PROVIDER", Table.class);
|
String identityProviderTableName = database.correctObjectName("IDENTITY_PROVIDER", Table.class);
|
||||||
String idpConfigTableName = database.correctObjectName("IDENTITY_PROVIDER_CONFIG", Table.class);
|
String idpConfigTableName = database.correctObjectName("IDENTITY_PROVIDER_CONFIG", Table.class);
|
||||||
|
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select RSC.NAME, VALUE, REALM_ID, UPDATE_PROFILE_ON_SOC_LOGIN from REALM_SOCIAL_CONFIG RSC,REALM where RSC.REALM_ID = REALM.ID ORDER BY RSC.REALM_ID, RSC.NAME");
|
String realmSocialConfigTable = getTableName("REALM_SOCIAL_CONFIG");
|
||||||
|
String realmTableName = getTableName("REALM");
|
||||||
|
PreparedStatement statement = jdbcConnection.prepareStatement("select RSC.NAME, VALUE, REALM_ID, UPDATE_PROFILE_ON_SOC_LOGIN from " + realmSocialConfigTable + " RSC," + realmTableName +
|
||||||
|
" REALM where RSC.REALM_ID = REALM.ID ORDER BY RSC.REALM_ID, RSC.NAME");
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
try {
|
try {
|
||||||
@@ -124,7 +128,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
|
|
||||||
protected void convertSocialToIdFedUsers() throws SQLException, DatabaseException {
|
protected void convertSocialToIdFedUsers() throws SQLException, DatabaseException {
|
||||||
String federatedIdentityTableName = database.correctObjectName("FEDERATED_IDENTITY", Table.class);
|
String federatedIdentityTableName = database.correctObjectName("FEDERATED_IDENTITY", Table.class);
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select REALM_ID, USER_ID, SOCIAL_PROVIDER, SOCIAL_USER_ID, SOCIAL_USERNAME from USER_SOCIAL_LINK");
|
PreparedStatement statement = jdbcConnection.prepareStatement("select REALM_ID, USER_ID, SOCIAL_PROVIDER, SOCIAL_USER_ID, SOCIAL_USERNAME from " + getTableName("USER_SOCIAL_LINK"));
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
try {
|
try {
|
||||||
@@ -170,7 +174,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
String adminRoleId = getAdminRoleId();
|
String adminRoleId = getAdminRoleId();
|
||||||
String masterRealmId = Config.getAdminRealm();
|
String masterRealmId = Config.getAdminRealm();
|
||||||
|
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select NAME from REALM");
|
PreparedStatement statement = jdbcConnection.prepareStatement("select NAME from " + getTableName("REALM"));
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
try {
|
try {
|
||||||
@@ -178,7 +182,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
String realmName = resultSet.getString("NAME");
|
String realmName = resultSet.getString("NAME");
|
||||||
String masterAdminAppName = realmName + "-realm";
|
String masterAdminAppName = realmName + "-realm";
|
||||||
|
|
||||||
PreparedStatement statement2 = jdbcConnection.prepareStatement("select ID from CLIENT where REALM_ID = ? AND NAME = ?");
|
PreparedStatement statement2 = jdbcConnection.prepareStatement("select ID from " + getTableName("CLIENT") + " where REALM_ID = ? AND NAME = ?");
|
||||||
statement2.setString(1, masterRealmId);
|
statement2.setString(1, masterRealmId);
|
||||||
statement2.setString(2, masterAdminAppName);
|
statement2.setString(2, masterAdminAppName);
|
||||||
|
|
||||||
@@ -209,7 +213,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getAdminRoleId() throws SQLException, DatabaseException {
|
private String getAdminRoleId() throws SQLException, DatabaseException {
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select ID from KEYCLOAK_ROLE where NAME = ? AND REALM = ?");
|
PreparedStatement statement = jdbcConnection.prepareStatement("select ID from " + getTableName("KEYCLOAK_ROLE") + " where NAME = ? AND REALM = ?");
|
||||||
statement.setString(1, AdminRoles.ADMIN);
|
statement.setString(1, AdminRoles.ADMIN);
|
||||||
statement.setString(2, Config.getAdminRealm());
|
statement.setString(2, Config.getAdminRealm());
|
||||||
|
|
||||||
@@ -231,7 +235,8 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
|
|
||||||
|
|
||||||
protected void addNewRealmAdminRoles() throws SQLException, DatabaseException {
|
protected void addNewRealmAdminRoles() throws SQLException, DatabaseException {
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select CLIENT.ID REALM_ADMIN_APP_ID, CLIENT.REALM_ID REALM_ID, KEYCLOAK_ROLE.ID ADMIN_ROLE_ID from CLIENT,KEYCLOAK_ROLE where KEYCLOAK_ROLE.APPLICATION = CLIENT.ID AND CLIENT.NAME = 'realm-management' AND KEYCLOAK_ROLE.NAME = ?");
|
PreparedStatement statement = jdbcConnection.prepareStatement("select CLIENT.ID REALM_ADMIN_APP_ID, CLIENT.REALM_ID REALM_ID, KEYCLOAK_ROLE.ID ADMIN_ROLE_ID from " +
|
||||||
|
getTableName("CLIENT") + " CLIENT," + getTableName("KEYCLOAK_ROLE") + " KEYCLOAK_ROLE where KEYCLOAK_ROLE.APPLICATION = CLIENT.ID AND CLIENT.NAME = 'realm-management' AND KEYCLOAK_ROLE.NAME = ?");
|
||||||
statement.setString(1, AdminRoles.REALM_ADMIN);
|
statement.setString(1, AdminRoles.REALM_ADMIN);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -280,7 +285,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
String protocolMapperTableName = database.correctObjectName("PROTOCOL_MAPPER", Table.class);
|
String protocolMapperTableName = database.correctObjectName("PROTOCOL_MAPPER", Table.class);
|
||||||
String protocolMapperCfgTableName = database.correctObjectName("PROTOCOL_MAPPER_CONFIG", Table.class);
|
String protocolMapperCfgTableName = database.correctObjectName("PROTOCOL_MAPPER_CONFIG", Table.class);
|
||||||
|
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select ID, NAME, ALLOWED_CLAIMS_MASK from CLIENT");
|
PreparedStatement statement = jdbcConnection.prepareStatement("select ID, NAME, ALLOWED_CLAIMS_MASK from " + getTableName("CLIENT"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
@@ -293,7 +298,7 @@ public class JpaUpdate1_2_0_Beta1 extends CustomKeycloakTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Object acmObj = resultSet.getObject("ALLOWED_CLAIMS_MASK");
|
Object acmObj = resultSet.getObject("ALLOWED_CLAIMS_MASK");
|
||||||
long mask = (acmObj != null) ? (Long) acmObj : ClaimMask.ALL;
|
long mask = (acmObj != null) ? ((Number) acmObj).longValue() : ClaimMask.ALL;
|
||||||
|
|
||||||
MigrationProvider migrationProvider = this.kcSession.getProvider(MigrationProvider.class);
|
MigrationProvider migrationProvider = this.kcSession.getProvider(MigrationProvider.class);
|
||||||
List<ProtocolMapperRepresentation> protocolMappers = migrationProvider.getMappersForClaimMask(mask);
|
List<ProtocolMapperRepresentation> protocolMappers = migrationProvider.getMappersForClaimMask(mask);
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ public class JpaUpdate1_2_0_CR1 extends CustomKeycloakTask {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
String trueValue = DataTypeFactory.getInstance().getTrueBooleanValue(database);
|
String trueValue = DataTypeFactory.getInstance().getTrueBooleanValue(database);
|
||||||
PreparedStatement statement = jdbcConnection.prepareStatement("select CLIENT.REALM_ID, CLIENT.ID CLIENT_ID from CLIENT where CLIENT.CONSENT_REQUIRED = " + trueValue);
|
PreparedStatement statement = jdbcConnection.prepareStatement("select CLIENT.REALM_ID, CLIENT.ID CLIENT_ID from " + getTableName("CLIENT") + " CLIENT where CLIENT.CONSENT_REQUIRED = " + trueValue);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = statement.executeQuery();
|
ResultSet resultSet = statement.executeQuery();
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package org.keycloak.connections.jpa.updater.liquibase.custom;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
|
||||||
|
import liquibase.datatype.DataTypeFactory;
|
||||||
|
import liquibase.exception.CustomChangeException;
|
||||||
|
import liquibase.statement.core.InsertStatement;
|
||||||
|
import liquibase.statement.core.UpdateStatement;
|
||||||
|
import liquibase.structure.core.Table;
|
||||||
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class JpaUpdate1_4_0_Final extends CustomKeycloakTask {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateStatementsImpl() throws CustomChangeException {
|
||||||
|
String userAttributeTableName = database.correctObjectName("USER_ATTRIBUTE", Table.class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
PreparedStatement statement = jdbcConnection.prepareStatement("select NAME, USER_ID from " + getTableName("USER_ATTRIBUTE"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResultSet resultSet = statement.executeQuery();
|
||||||
|
try {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String name = resultSet.getString(1);
|
||||||
|
String userId = resultSet.getString(2);
|
||||||
|
|
||||||
|
UpdateStatement updateStatement = new UpdateStatement(null, null, userAttributeTableName)
|
||||||
|
.addNewColumnValue("ID", KeycloakModelUtils.generateId())
|
||||||
|
.setWhereClause("NAME='" + name + "' AND USER_ID='" + userId + "'");
|
||||||
|
statements.add(updateStatement);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
resultSet.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmationMessage.append("Updated " + statements.size() + " attributes in USER_ATTRIBUTE table");
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CustomChangeException(getTaskId() + ": Exception when updating data from previous version", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTaskId() {
|
||||||
|
return "Update 1.4.0.Final";
|
||||||
|
}
|
||||||
|
}
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
<changeSet author="bburke@redhat.com" id="1.4.0">
|
||||||
|
<delete tableName="CLIENT_SESSION_AUTH_STATUS"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_ROLE"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_PROT_MAPPER"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_NOTE"/>
|
||||||
|
<delete tableName="CLIENT_SESSION"/>
|
||||||
|
<delete tableName="USER_SESSION_NOTE"/>
|
||||||
|
<delete tableName="USER_SESSION"/>
|
||||||
|
|
||||||
|
<addColumn tableName="CLIENT">
|
||||||
|
<column name="SERVICE_ACCOUNTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="AUTHENTICATION_FLOW">
|
||||||
|
<column name="PROVIDER_ID" type="VARCHAR(36)" defaultValue="basic-flow">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="TOP_LEVEL" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="BUILT_IN" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="AUTHENTICATION_EXECUTION">
|
||||||
|
<column name="AUTH_FLOW_ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="AUTH_CONFIG" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="USER_ATTRIBUTE">
|
||||||
|
<column name="ID" type="VARCHAR(36)" defaultValue="sybase-needs-something-here">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
|
||||||
|
<dropColumn tableName="AUTHENTICATOR" columnName="PROVIDER_ID"/>
|
||||||
|
<renameTable oldTableName="AUTHENTICATOR_CONFIG" newTableName="AUTHENTICATOR_CONFIG_ENTRY"/>
|
||||||
|
<renameTable oldTableName="AUTHENTICATOR" newTableName="AUTHENTICATOR_CONFIG"/>
|
||||||
|
<!-- OAUTH_GRANT,
|
||||||
|
CODE_TO_TOKEN,
|
||||||
|
VERIFY_EMAIL,
|
||||||
|
UPDATE_PROFILE,
|
||||||
|
CONFIGURE_TOTP,
|
||||||
|
UPDATE_PASSWORD,
|
||||||
|
RECOVER_PASSWORD,
|
||||||
|
AUTHENTICATE,
|
||||||
|
SOCIAL_CALLBACK,
|
||||||
|
LOGGED_OUT -->
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="OAUTH_GRANT"/>
|
||||||
|
<where>ACTION = 0</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="CODE_TO_TOKEN"/>
|
||||||
|
<where>ACTION = 1</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="VERIFY_EMAIL"/>
|
||||||
|
<where>ACTION = 2</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="UPDATE_PROFILE"/>
|
||||||
|
<where>ACTION = 3</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="CONFIGURE_TOTP"/>
|
||||||
|
<where>ACTION = 4</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="UPDATE_PASSWORD"/>
|
||||||
|
<where>ACTION = 5</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="RECOVER_PASSWORD"/>
|
||||||
|
<where>ACTION = 6</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="AUTHENTICATE"/>
|
||||||
|
<where>ACTION = 7</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="SOCIAL_CALLBACK"/>
|
||||||
|
<where>ACTION = 8</where>
|
||||||
|
</update>
|
||||||
|
<update tableName="CLIENT_SESSION">
|
||||||
|
<column name="CURRENT_ACTION" value="LOGGED_OUT"/>
|
||||||
|
<where>ACTION = 9</where>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<createTable tableName="CLIENT_USER_SESSION_NOTE">
|
||||||
|
<column name="NAME" type="VARCHAR(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="VALUE" type="VARCHAR(2048)"/>
|
||||||
|
<column name="CLIENT_SESSION" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</createTable>
|
||||||
|
<createTable tableName="REQUIRED_ACTION_PROVIDER">
|
||||||
|
<column name="ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="ALIAS" type="VARCHAR(255)"/>
|
||||||
|
<column name="NAME" type="VARCHAR(255)"/>
|
||||||
|
<column name="REALM_ID" type="VARCHAR(36)"/>
|
||||||
|
<column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="DEFAULT_ACTION" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="PROVIDER_ID" type="VARCHAR(255)"/>
|
||||||
|
</createTable>
|
||||||
|
<createTable tableName="REQUIRED_ACTION_CONFIG">
|
||||||
|
<column name="REQUIRED_ACTION_ID" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="VALUE" type="CLOB"/>
|
||||||
|
<column name="NAME" type="VARCHAR(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</createTable>
|
||||||
|
|
||||||
|
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.JpaUpdate1_4_0_Final"/>
|
||||||
|
|
||||||
|
<dropPrimaryKey constraintName="CONSTRAINT_6" tableName="USER_ATTRIBUTE"/>
|
||||||
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_USER_ATTRIBUTE_PK" tableName="USER_ATTRIBUTE"/>
|
||||||
|
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_REQ_ACT_PRV_PK" tableName="REQUIRED_ACTION_PROVIDER"/>
|
||||||
|
<addPrimaryKey columnNames="REQUIRED_ACTION_ID, NAME" constraintName="CONSTRAINT_REQ_ACT_CFG_PK" tableName="REQUIRED_ACTION_CONFIG"/>
|
||||||
|
<addPrimaryKey columnNames="CLIENT_SESSION, NAME" constraintName="CONSTR_CL_USR_SES_NOTE" tableName="CLIENT_USER_SESSION_NOTE"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REQUIRED_ACTION_PROVIDER" constraintName="FK_REQ_ACT_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_USER_SESSION_NOTE" constraintName="FK_CL_USR_SES_NOTE" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
|
||||||
|
<dropColumn tableName="CLIENT_SESSION" columnName="ACTION"/>
|
||||||
|
<addColumn tableName="USER_ENTITY">
|
||||||
|
<column name="CREATED_TIMESTAMP" type="BIGINT"/>
|
||||||
|
<column name="SERVICE_ACCOUNT_CLIENT_LINK" type="VARCHAR(36)"/>
|
||||||
|
</addColumn>
|
||||||
|
|
||||||
|
<!-- Sybase specific hacks -->
|
||||||
|
<modifySql dbms="sybase">
|
||||||
|
<replace replace="[USER_ATTRIBUTE] DROP PRIMARY KEY" with="[USER_ATTRIBUTE] DROP CONSTRAINT CONSTRAINT_6" />
|
||||||
|
</modifySql>
|
||||||
|
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
<changeSet author="bburke@redhat.com" id="1.5.0">
|
||||||
|
<delete tableName="CLIENT_SESSION_AUTH_STATUS"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_ROLE"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_PROT_MAPPER"/>
|
||||||
|
<delete tableName="CLIENT_SESSION_NOTE"/>
|
||||||
|
<delete tableName="CLIENT_SESSION"/>
|
||||||
|
<delete tableName="USER_SESSION_NOTE"/>
|
||||||
|
<delete tableName="USER_SESSION"/>
|
||||||
|
|
||||||
|
<dropDefaultValue tableName="AUTHENTICATION_EXECUTION" columnName="USER_SETUP_ALLOWED" />
|
||||||
|
<dropColumn tableName="AUTHENTICATION_EXECUTION" columnName="USER_SETUP_ALLOWED"/>
|
||||||
|
<addColumn tableName="CREDENTIAL">
|
||||||
|
<column name="COUNTER" type="INT" defaultValueNumeric="0">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="DIGITS" type="INT" defaultValueNumeric="6">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="PERIOD" type="INT" defaultValueNumeric="30">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="ALGORITHM" type="VARCHAR(36)" defaultValue="HmacSHA1">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="REALM">
|
||||||
|
<column name="OTP_POLICY_COUNTER" type="INT" defaultValueNumeric="0">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="OTP_POLICY_WINDOW" type="INT" defaultValueNumeric="1">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="OTP_POLICY_PERIOD" type="INT" defaultValueNumeric="30">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="OTP_POLICY_DIGITS" type="INT" defaultValueNumeric="6">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="OTP_POLICY_ALG" type="VARCHAR(36)" defaultValue="HmacSHA1">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="OTP_POLICY_TYPE" type="VARCHAR(36)" defaultValue="totp">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="BROWSER_FLOW" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="REGISTRATION_FLOW" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="DIRECT_GRANT_FLOW" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="RESET_CREDENTIALS_FLOW" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="CLIENT_AUTH_FLOW" type="VARCHAR(36)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
|
||||||
|
<addColumn tableName="CLIENT">
|
||||||
|
<column name="CLIENT_AUTHENTICATOR_TYPE" type="VARCHAR(255)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
|
||||||
|
<!-- Sybase specific hacks -->
|
||||||
|
<modifySql dbms="sybase">
|
||||||
|
<regExpReplace replace=".*(SET DEFAULT NULL)" with="SELECT 1" />
|
||||||
|
</modifySql>
|
||||||
|
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -7,4 +7,6 @@
|
|||||||
<include file="META-INF/jpa-changelog-1.2.0.CR1.xml"/>
|
<include file="META-INF/jpa-changelog-1.2.0.CR1.xml"/>
|
||||||
<include file="META-INF/jpa-changelog-1.2.0.Final.xml"/>
|
<include file="META-INF/jpa-changelog-1.2.0.Final.xml"/>
|
||||||
<include file="META-INF/jpa-changelog-1.3.0.xml"/>
|
<include file="META-INF/jpa-changelog-1.3.0.xml"/>
|
||||||
|
<include file="META-INF/jpa-changelog-1.4.0.xml"/>
|
||||||
|
<include file="META-INF/jpa-changelog-1.5.0.xml"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
+38
-10
@@ -4,6 +4,7 @@ import org.hibernate.ejb.AvailableSettings;
|
|||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
|
||||||
|
import org.keycloak.connections.jpa.util.JpaUtils;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
@@ -13,10 +14,12 @@ import javax.persistence.EntityManagerFactory;
|
|||||||
import javax.persistence.Persistence;
|
import javax.persistence.Persistence;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +33,8 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
|
|
||||||
private Config.Scope config;
|
private Config.Scope config;
|
||||||
|
|
||||||
|
private Map<String,String> operationalInfo;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JpaConnectionProvider create(KeycloakSession session) {
|
public JpaConnectionProvider create(KeycloakSession session) {
|
||||||
lazyInit(session);
|
lazyInit(session);
|
||||||
@@ -70,14 +75,11 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
|
|
||||||
Connection connection = null;
|
Connection connection = null;
|
||||||
|
|
||||||
String unitName = config.get("unitName");
|
|
||||||
String databaseSchema = config.get("databaseSchema");
|
String databaseSchema = config.get("databaseSchema");
|
||||||
|
|
||||||
Map<String, Object> properties = new HashMap<String, Object>();
|
Map<String, Object> properties = new HashMap<String, Object>();
|
||||||
|
|
||||||
// Only load config from keycloak-server.json if unitName is not specified
|
String unitName = "keycloak-default";
|
||||||
if (unitName == null) {
|
|
||||||
unitName = "keycloak-default";
|
|
||||||
|
|
||||||
String dataSource = config.get("dataSource");
|
String dataSource = config.get("dataSource");
|
||||||
if (dataSource != null) {
|
if (dataSource != null) {
|
||||||
@@ -105,6 +107,11 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
properties.put("hibernate.dialect", driverDialect);
|
properties.put("hibernate.dialect", driverDialect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String schema = config.get("schema");
|
||||||
|
if (schema != null) {
|
||||||
|
properties.put(JpaUtils.HIBERNATE_DEFAULT_SCHEMA, schema);
|
||||||
|
}
|
||||||
|
|
||||||
if (databaseSchema != null) {
|
if (databaseSchema != null) {
|
||||||
if (databaseSchema.equals("development-update")) {
|
if (databaseSchema.equals("development-update")) {
|
||||||
properties.put("hibernate.hbm2ddl.auto", "update");
|
properties.put("hibernate.hbm2ddl.auto", "update");
|
||||||
@@ -117,7 +124,10 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
|
|
||||||
properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
|
properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
|
||||||
properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
|
properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
|
||||||
}
|
|
||||||
|
connection = getConnection();
|
||||||
|
try{
|
||||||
|
prepareOperationalInfo(connection);
|
||||||
|
|
||||||
if (databaseSchema != null) {
|
if (databaseSchema != null) {
|
||||||
logger.trace("Updating database");
|
logger.trace("Updating database");
|
||||||
@@ -127,12 +137,10 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
throw new RuntimeException("Can't update database: JPA updater provider not found");
|
throw new RuntimeException("Can't update database: JPA updater provider not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = getConnection();
|
|
||||||
|
|
||||||
if (databaseSchema.equals("update")) {
|
if (databaseSchema.equals("update")) {
|
||||||
String currentVersion = null;
|
String currentVersion = null;
|
||||||
try {
|
try {
|
||||||
ResultSet resultSet = connection.createStatement().executeQuery(updater.getCurrentVersionSql());
|
ResultSet resultSet = connection.createStatement().executeQuery(updater.getCurrentVersionSql(schema));
|
||||||
if (resultSet.next()) {
|
if (resultSet.next()) {
|
||||||
currentVersion = resultSet.getString(1);
|
currentVersion = resultSet.getString(1);
|
||||||
}
|
}
|
||||||
@@ -140,12 +148,12 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (currentVersion == null || !JpaUpdaterProvider.LAST_VERSION.equals(currentVersion)) {
|
if (currentVersion == null || !JpaUpdaterProvider.LAST_VERSION.equals(currentVersion)) {
|
||||||
updater.update(session, connection);
|
updater.update(session, connection, schema);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Database is up to date");
|
logger.debug("Database is up to date");
|
||||||
}
|
}
|
||||||
} else if (databaseSchema.equals("validate")) {
|
} else if (databaseSchema.equals("validate")) {
|
||||||
updater.validate(connection);
|
updater.validate(connection, schema);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
|
throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
|
||||||
}
|
}
|
||||||
@@ -157,6 +165,7 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
emf = Persistence.createEntityManagerFactory(unitName, properties);
|
emf = Persistence.createEntityManagerFactory(unitName, properties);
|
||||||
logger.trace("EntityManagerFactory created");
|
logger.trace("EntityManagerFactory created");
|
||||||
|
|
||||||
|
} finally {
|
||||||
// Close after creating EntityManagerFactory to prevent in-mem databases from closing
|
// Close after creating EntityManagerFactory to prevent in-mem databases from closing
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
try {
|
try {
|
||||||
@@ -169,6 +178,20 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareOperationalInfo(Connection connection) {
|
||||||
|
try {
|
||||||
|
operationalInfo = new LinkedHashMap<>();
|
||||||
|
DatabaseMetaData md = connection.getMetaData();
|
||||||
|
operationalInfo.put("databaseUrl",md.getURL());
|
||||||
|
operationalInfo.put("databaseUser", md.getUserName());
|
||||||
|
operationalInfo.put("databaseProduct", md.getDatabaseProductName() + " " + md.getDatabaseProductVersion());
|
||||||
|
operationalInfo.put("databaseDriver", md.getDriverName() + " " + md.getDriverVersion());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.warn("Unable to prepare operational info due database exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Connection getConnection() {
|
private Connection getConnection() {
|
||||||
try {
|
try {
|
||||||
@@ -185,4 +208,9 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String,String> getOperationalInfo() {
|
||||||
|
return operationalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+3
-2
@@ -1,9 +1,10 @@
|
|||||||
package org.keycloak.connections.jpa;
|
package org.keycloak.connections.jpa;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
|
public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
|
||||||
|
|
||||||
}
|
}
|
||||||
+4
-4
@@ -12,12 +12,12 @@ public interface JpaUpdaterProvider extends Provider {
|
|||||||
|
|
||||||
public String FIRST_VERSION = "1.0.0.Final";
|
public String FIRST_VERSION = "1.0.0.Final";
|
||||||
|
|
||||||
public String LAST_VERSION = "1.3.0.Beta1";
|
public String LAST_VERSION = "1.5.0";
|
||||||
|
|
||||||
public String getCurrentVersionSql();
|
public String getCurrentVersionSql(String defaultSchema);
|
||||||
|
|
||||||
public void update(KeycloakSession session, Connection connection);
|
public void update(KeycloakSession session, Connection connection, String defaultSchema);
|
||||||
|
|
||||||
public void validate(Connection connection);
|
public void validate(Connection connection, String defaultSchema);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package org.keycloak.connections.jpa.util;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class JpaUtils {
|
||||||
|
|
||||||
|
public static final String HIBERNATE_DEFAULT_SCHEMA = "hibernate.default_schema";
|
||||||
|
|
||||||
|
public static String getTableNameForNativeQuery(String tableName, EntityManager em) {
|
||||||
|
String schema = (String) em.getEntityManagerFactory().getProperties().get(HIBERNATE_DEFAULT_SCHEMA);
|
||||||
|
return (schema==null) ? tableName : schema + "." + tableName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,17 +27,8 @@
|
|||||||
<class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserConsentProtocolMapperEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
|
<class>org.keycloak.models.jpa.entities.AuthenticationFlowEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
|
<class>org.keycloak.models.jpa.entities.AuthenticationExecutionEntity</class>
|
||||||
<class>org.keycloak.models.jpa.entities.AuthenticatorEntity</class>
|
<class>org.keycloak.models.jpa.entities.AuthenticatorConfigEntity</class>
|
||||||
|
<class>org.keycloak.models.jpa.entities.RequiredActionProviderEntity</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.ClientSessionAuthStatusEntity</class>
|
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity</class>
|
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity</class>
|
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity</class>
|
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
|
|
||||||
<class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
|
|
||||||
|
|
||||||
<!-- JpaAuditProviders -->
|
<!-- JpaAuditProviders -->
|
||||||
<class>org.keycloak.events.jpa.EventEntity</class>
|
<class>org.keycloak.events.jpa.EventEntity</class>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+2
-1
@@ -27,7 +27,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
|
|||||||
Update1_1_0_Beta1.class,
|
Update1_1_0_Beta1.class,
|
||||||
Update1_2_0_Beta1.class,
|
Update1_2_0_Beta1.class,
|
||||||
Update1_2_0_CR1.class,
|
Update1_2_0_CR1.class,
|
||||||
Update1_3_0.class
|
Update1_3_0.class,
|
||||||
|
Update1_4_0.class
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -249,7 +249,7 @@ public class Update1_2_0_Beta1 extends Update {
|
|||||||
dbMapper.put("protocolMapper", protocolMapper.getProtocolMapper());
|
dbMapper.put("protocolMapper", protocolMapper.getProtocolMapper());
|
||||||
|
|
||||||
Map<String, String> config = protocolMapper.getConfig();
|
Map<String, String> config = protocolMapper.getConfig();
|
||||||
BasicDBObject dbConfig = MapMapper.convertMap(config);
|
BasicDBObject dbConfig = MapMapper.convertMap(config, null);
|
||||||
dbMapper.put("config", dbConfig);
|
dbMapper.put("config", dbConfig);
|
||||||
|
|
||||||
dbProtocolMappers.add(dbMapper);
|
dbProtocolMappers.add(dbMapper);
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
package org.keycloak.connections.mongo.updater.impl.updates;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBList;
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
|
import com.mongodb.DBCollection;
|
||||||
|
import com.mongodb.DBCursor;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class Update1_4_0 extends Update {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "1.4.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(KeycloakSession session) throws ClassNotFoundException {
|
||||||
|
deleteEntries("clientSessions");
|
||||||
|
deleteEntries("sessions");
|
||||||
|
|
||||||
|
// Remove warning
|
||||||
|
removeField("realms", "authenticators");
|
||||||
|
|
||||||
|
updateUserAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUserAttributes() {
|
||||||
|
DBCollection users = db.getCollection("users");
|
||||||
|
DBCursor usersCursor = users.find();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (usersCursor.hasNext()) {
|
||||||
|
BasicDBObject user = (BasicDBObject) usersCursor.next();
|
||||||
|
|
||||||
|
BasicDBObject attributes = (BasicDBObject) user.get("attributes");
|
||||||
|
if (attributes != null) {
|
||||||
|
for (Map.Entry<String, Object> attr : new HashSet<>(attributes.entrySet())) {
|
||||||
|
String attrName = attr.getKey();
|
||||||
|
Object attrValue = attr.getValue();
|
||||||
|
if (attrValue != null && attrValue instanceof String) {
|
||||||
|
BasicDBList asList = new BasicDBList();
|
||||||
|
asList.add(attrValue);
|
||||||
|
attributes.put(attrName, asList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
user.put("attributes", attributes);
|
||||||
|
|
||||||
|
users.save(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
usersCursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+22
-8
@@ -5,6 +5,7 @@ import com.mongodb.MongoClient;
|
|||||||
import com.mongodb.MongoClientOptions;
|
import com.mongodb.MongoClientOptions;
|
||||||
import com.mongodb.MongoCredential;
|
import com.mongodb.MongoCredential;
|
||||||
import com.mongodb.ServerAddress;
|
import com.mongodb.ServerAddress;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.connections.mongo.api.MongoStore;
|
import org.keycloak.connections.mongo.api.MongoStore;
|
||||||
@@ -18,35 +19,35 @@ import javax.net.ssl.SSLSocketFactory;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
|
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
|
||||||
|
|
||||||
// TODO Make configurable
|
// TODO Make it dynamic
|
||||||
private String[] entities = new String[]{
|
private String[] entities = new String[]{
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
|
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
|
||||||
|
"org.keycloak.models.mongo.keycloak.entities.MongoClientEntity",
|
||||||
|
"org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity",
|
||||||
|
"org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity",
|
||||||
"org.keycloak.models.entities.IdentityProviderEntity",
|
"org.keycloak.models.entities.IdentityProviderEntity",
|
||||||
"org.keycloak.models.entities.ClientIdentityProviderMappingEntity",
|
"org.keycloak.models.entities.ClientIdentityProviderMappingEntity",
|
||||||
"org.keycloak.models.entities.RequiredCredentialEntity",
|
"org.keycloak.models.entities.RequiredCredentialEntity",
|
||||||
"org.keycloak.models.entities.CredentialEntity",
|
"org.keycloak.models.entities.CredentialEntity",
|
||||||
"org.keycloak.models.entities.FederatedIdentityEntity",
|
"org.keycloak.models.entities.FederatedIdentityEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoClientEntity",
|
|
||||||
"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",
|
"org.keycloak.models.entities.UserFederationProviderEntity",
|
||||||
"org.keycloak.models.entities.UserFederationMapperEntity",
|
"org.keycloak.models.entities.UserFederationMapperEntity",
|
||||||
"org.keycloak.models.entities.ProtocolMapperEntity",
|
"org.keycloak.models.entities.ProtocolMapperEntity",
|
||||||
"org.keycloak.models.entities.IdentityProviderMapperEntity",
|
"org.keycloak.models.entities.IdentityProviderMapperEntity",
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity",
|
|
||||||
"org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity",
|
|
||||||
"org.keycloak.models.entities.AuthenticationExecutionEntity",
|
"org.keycloak.models.entities.AuthenticationExecutionEntity",
|
||||||
"org.keycloak.models.entities.AuthenticationFlowEntity",
|
"org.keycloak.models.entities.AuthenticationFlowEntity",
|
||||||
"org.keycloak.models.entities.AuthenticatorEntity",
|
"org.keycloak.models.entities.AuthenticatorConfigEntity",
|
||||||
|
"org.keycloak.models.entities.RequiredActionProviderEntity",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
|
private static final Logger logger = Logger.getLogger(DefaultMongoConnectionFactoryProvider.class);
|
||||||
@@ -57,6 +58,8 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
|||||||
private DB db;
|
private DB db;
|
||||||
protected Config.Scope config;
|
protected Config.Scope config;
|
||||||
|
|
||||||
|
private Map<String,String> operationalInfo;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MongoConnectionProvider create(KeycloakSession session) {
|
public MongoConnectionProvider create(KeycloakSession session) {
|
||||||
lazyInit(session);
|
lazyInit(session);
|
||||||
@@ -159,6 +162,12 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
|||||||
client = new MongoClient(new ServerAddress(host, port), clientOptions);
|
client = new MongoClient(new ServerAddress(host, port), clientOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operationalInfo = new LinkedHashMap<>();
|
||||||
|
operationalInfo.put("mongoServerAddress", client.getAddress().toString());
|
||||||
|
operationalInfo.put("mongoDatabaseName", dbName);
|
||||||
|
operationalInfo.put("mongoUser", user);
|
||||||
|
operationalInfo.put("mongoDriverVersion", client.getVersion());
|
||||||
|
|
||||||
logger.debugv("Initialized mongo model. host: %s, port: %d, db: %s", host, port, dbName);
|
logger.debugv("Initialized mongo model. host: %s, port: %d, db: %s", host, port, dbName);
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
@@ -206,4 +215,9 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String,String> getOperationalInfo() {
|
||||||
|
return operationalInfo;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
package org.keycloak.connections.mongo;
|
package org.keycloak.connections.mongo;
|
||||||
|
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ServerInfoAwareProviderFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
|
public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
|
||||||
}
|
}
|
||||||
+4
-3
@@ -1,5 +1,6 @@
|
|||||||
package org.keycloak.connections.mongo.api.types;
|
package org.keycloak.connections.mongo.api.types;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,9 +15,9 @@ public class MapperContext<T, S> {
|
|||||||
private final Class<? extends S> expectedReturnType;
|
private final Class<? extends S> expectedReturnType;
|
||||||
|
|
||||||
// in case that expected return type is generic type (like "List<String>"), then genericTypes could contain list of expected generic arguments
|
// in case that expected return type is generic type (like "List<String>"), then genericTypes could contain list of expected generic arguments
|
||||||
private final List<Class<?>> genericTypes;
|
private final List<Type> genericTypes;
|
||||||
|
|
||||||
public MapperContext(T objectToConvert, Class<? extends S> expectedReturnType, List<Class<?>> genericTypes) {
|
public MapperContext(T objectToConvert, Class<? extends S> expectedReturnType, List<Type> genericTypes) {
|
||||||
this.objectToConvert = objectToConvert;
|
this.objectToConvert = objectToConvert;
|
||||||
this.expectedReturnType = expectedReturnType;
|
this.expectedReturnType = expectedReturnType;
|
||||||
this.genericTypes = genericTypes;
|
this.genericTypes = genericTypes;
|
||||||
@@ -30,7 +31,7 @@ public class MapperContext<T, S> {
|
|||||||
return expectedReturnType;
|
return expectedReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Class<?>> getGenericTypes() {
|
public List<Type> getGenericTypes() {
|
||||||
return genericTypes;
|
return genericTypes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
@@ -47,6 +47,10 @@ public class MapperRegistry {
|
|||||||
|
|
||||||
|
|
||||||
public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
|
public <S> S convertDBObjectToApplicationObject(MapperContext<Object, S> context) {
|
||||||
|
if (context.getObjectToConvert() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Object dbObject = context.getObjectToConvert();
|
Object dbObject = context.getObjectToConvert();
|
||||||
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
|
Class<?> expectedApplicationObjectType = context.getExpectedReturnType();
|
||||||
|
|
||||||
@@ -74,6 +78,10 @@ public class MapperRegistry {
|
|||||||
|
|
||||||
|
|
||||||
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
|
public <S> S convertApplicationObjectToDBObject(Object applicationObject, Class<S> expectedDBObjectType) {
|
||||||
|
if (applicationObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> appObjectType = applicationObject.getClass();
|
Class<?> appObjectType = applicationObject.getClass();
|
||||||
Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
|
Mapper<Object, S> mapper = (Mapper<Object, S>)getAppConverterForType(appObjectType, appObjectMappers);
|
||||||
if (mapper == null) {
|
if (mapper == null) {
|
||||||
|
|||||||
+3
-3
@@ -79,9 +79,9 @@ public class MongoStoreImpl implements MongoStore {
|
|||||||
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, Set.class));
|
mapperRegistry.addAppObjectMapper(new ListMapper(mapperRegistry, Set.class));
|
||||||
mapperRegistry.addDBObjectMapper(new BasicDBListToSetMapper(mapperRegistry));
|
mapperRegistry.addDBObjectMapper(new BasicDBListToSetMapper(mapperRegistry));
|
||||||
|
|
||||||
mapperRegistry.addAppObjectMapper(new MapMapper(HashMap.class));
|
mapperRegistry.addAppObjectMapper(new MapMapper(mapperRegistry, HashMap.class));
|
||||||
mapperRegistry.addAppObjectMapper(new MapMapper(Map.class));
|
mapperRegistry.addAppObjectMapper(new MapMapper(mapperRegistry, Map.class));
|
||||||
mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper());
|
mapperRegistry.addDBObjectMapper(new BasicDBObjectToMapMapper(mapperRegistry));
|
||||||
|
|
||||||
// Enum converters
|
// Enum converters
|
||||||
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
|
mapperRegistry.addAppObjectMapper(new EnumToStringMapper());
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ public class BasicDBListMapper implements Mapper<BasicDBList, List> {
|
|||||||
public List convertObject(MapperContext<BasicDBList, List> context) {
|
public List convertObject(MapperContext<BasicDBList, List> context) {
|
||||||
BasicDBList dbList = context.getObjectToConvert();
|
BasicDBList dbList = context.getObjectToConvert();
|
||||||
ArrayList<Object> appObjects = new ArrayList<Object>();
|
ArrayList<Object> appObjects = new ArrayList<Object>();
|
||||||
Class<?> expectedListElementType = context.getGenericTypes().get(0);
|
Class<?> expectedListElementType = (Class<?>) context.getGenericTypes().get(0);
|
||||||
|
|
||||||
for (Object dbObject : dbList) {
|
for (Object dbObject : dbList) {
|
||||||
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
|
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ public class BasicDBListToSetMapper implements Mapper<BasicDBList, Set> {
|
|||||||
public Set convertObject(MapperContext<BasicDBList, Set> context) {
|
public Set convertObject(MapperContext<BasicDBList, Set> context) {
|
||||||
BasicDBList dbList = context.getObjectToConvert();
|
BasicDBList dbList = context.getObjectToConvert();
|
||||||
Set<Object> appObjects = new HashSet<Object>();
|
Set<Object> appObjects = new HashSet<Object>();
|
||||||
Class<?> expectedListElementType = context.getGenericTypes().get(0);
|
Class<?> expectedListElementType = (Class<?>) context.getGenericTypes().get(0);
|
||||||
|
|
||||||
for (Object dbObject : dbList) {
|
for (Object dbObject : dbList) {
|
||||||
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
|
MapperContext<Object, Object> newContext = new MapperContext<Object, Object>(dbObject, expectedListElementType, null);
|
||||||
|
|||||||
+2
-4
@@ -14,6 +14,7 @@ import org.keycloak.util.reflections.Types;
|
|||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,10 +88,7 @@ public class BasicDBObjectMapper<S> implements Mapper<BasicDBObject, S> {
|
|||||||
ParameterizedType parameterized = (ParameterizedType) type;
|
ParameterizedType parameterized = (ParameterizedType) type;
|
||||||
Type[] genericTypeArguments = parameterized.getActualTypeArguments();
|
Type[] genericTypeArguments = parameterized.getActualTypeArguments();
|
||||||
|
|
||||||
List<Class<?>> genericTypes = new ArrayList<Class<?>>();
|
List<Type> genericTypes = Arrays.asList(genericTypeArguments);
|
||||||
for (Type genericType : genericTypeArguments) {
|
|
||||||
genericTypes.add((Class<?>)genericType);
|
|
||||||
}
|
|
||||||
|
|
||||||
Class<?> expectedReturnType = (Class<?>)parameterized.getRawType();
|
Class<?> expectedReturnType = (Class<?>)parameterized.getRawType();
|
||||||
context = new MapperContext<Object, Object>(valueFromDB, expectedReturnType, genericTypes);
|
context = new MapperContext<Object, Object>(valueFromDB, expectedReturnType, genericTypes);
|
||||||
|
|||||||
+32
-4
@@ -3,31 +3,44 @@ package org.keycloak.connections.mongo.impl.types;
|
|||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.keycloak.connections.mongo.api.types.Mapper;
|
import org.keycloak.connections.mongo.api.types.Mapper;
|
||||||
import org.keycloak.connections.mongo.api.types.MapperContext;
|
import org.keycloak.connections.mongo.api.types.MapperContext;
|
||||||
|
import org.keycloak.connections.mongo.api.types.MapperRegistry;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, there is support just for convert to Map<String, simpleType>
|
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public class BasicDBObjectToMapMapper implements Mapper<BasicDBObject, Map> {
|
public class BasicDBObjectToMapMapper implements Mapper<BasicDBObject, Map> {
|
||||||
|
|
||||||
|
private final MapperRegistry mapperRegistry;
|
||||||
|
|
||||||
|
public BasicDBObjectToMapMapper(MapperRegistry mapperRegistry) {
|
||||||
|
this.mapperRegistry = mapperRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map convertObject(MapperContext<BasicDBObject, Map> context) {
|
public Map convertObject(MapperContext<BasicDBObject, Map> context) {
|
||||||
BasicDBObject dbObjectToConvert = context.getObjectToConvert();
|
BasicDBObject dbObjectToConvert = context.getObjectToConvert();
|
||||||
|
Type expectedElementValueType = context.getGenericTypes().get(1);
|
||||||
|
|
||||||
HashMap<String, Object> result = new HashMap<String, Object>();
|
HashMap<String, Object> result = new HashMap<String, Object>();
|
||||||
for (Map.Entry<String, Object> entry : dbObjectToConvert.entrySet()) {
|
for (Map.Entry<String, Object> entry : dbObjectToConvert.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
Object value = entry.getValue();
|
Object dbValue = entry.getValue();
|
||||||
|
|
||||||
// Workaround as manually inserted numbers into mongo may be treated as "Double"
|
// Workaround as manually inserted numbers into mongo may be treated as "Double"
|
||||||
if (value instanceof Double && context.getGenericTypes().get(1) == Integer.class) {
|
if (dbValue instanceof Double && expectedElementValueType == Integer.class) {
|
||||||
value = ((Double)value).intValue();
|
dbValue = ((Double)dbValue).intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapperContext<Object, Object> newContext = getMapperContext(dbValue, expectedElementValueType);
|
||||||
|
Object value = mapperRegistry.convertDBObjectToApplicationObject(newContext);
|
||||||
|
|
||||||
if (key.contains(MapMapper.DOT_PLACEHOLDER)) {
|
if (key.contains(MapMapper.DOT_PLACEHOLDER)) {
|
||||||
key = key.replaceAll(MapMapper.DOT_PLACEHOLDER, ".");
|
key = key.replaceAll(MapMapper.DOT_PLACEHOLDER, ".");
|
||||||
}
|
}
|
||||||
@@ -46,4 +59,19 @@ public class BasicDBObjectToMapMapper implements Mapper<BasicDBObject, Map> {
|
|||||||
public Class<Map> getExpectedReturnType() {
|
public Class<Map> getExpectedReturnType() {
|
||||||
return Map.class;
|
return Map.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MapperContext<Object, Object> getMapperContext(Object dbValue, Type expectedElementValueType) {
|
||||||
|
if (expectedElementValueType instanceof Class) {
|
||||||
|
Class<?> clazz = (Class<?>) expectedElementValueType;
|
||||||
|
return new MapperContext<>(dbValue, clazz, null);
|
||||||
|
} else if (expectedElementValueType instanceof ParameterizedType) {
|
||||||
|
ParameterizedType parameterized = (ParameterizedType) expectedElementValueType;
|
||||||
|
Class<?> expectedClazz = (Class<?>) parameterized.getRawType();
|
||||||
|
Type[] generics = parameterized.getActualTypeArguments();
|
||||||
|
|
||||||
|
return new MapperContext<>(dbValue, expectedClazz, Arrays.asList(generics));
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unexpected type: '" + expectedElementValueType + "' for converting " + dbValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+9
-4
@@ -3,6 +3,7 @@ package org.keycloak.connections.mongo.impl.types;
|
|||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.keycloak.connections.mongo.api.types.Mapper;
|
import org.keycloak.connections.mongo.api.types.Mapper;
|
||||||
import org.keycloak.connections.mongo.api.types.MapperContext;
|
import org.keycloak.connections.mongo.api.types.MapperContext;
|
||||||
|
import org.keycloak.connections.mongo.api.types.MapperRegistry;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -17,30 +18,34 @@ public class MapMapper<T extends Map> implements Mapper<T, BasicDBObject> {
|
|||||||
// Just some dummy way of encoding . character as it's not allowed by mongo in key fields
|
// Just some dummy way of encoding . character as it's not allowed by mongo in key fields
|
||||||
static final String DOT_PLACEHOLDER = "###";
|
static final String DOT_PLACEHOLDER = "###";
|
||||||
|
|
||||||
|
private final MapperRegistry mapperRegistry;
|
||||||
private final Class<T> mapType;
|
private final Class<T> mapType;
|
||||||
|
|
||||||
public MapMapper(Class<T> mapType) {
|
public MapMapper(MapperRegistry mapperRegistry, Class<T> mapType) {
|
||||||
|
this.mapperRegistry = mapperRegistry;
|
||||||
this.mapType = mapType;
|
this.mapType = mapType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
|
public BasicDBObject convertObject(MapperContext<T, BasicDBObject> context) {
|
||||||
T mapToConvert = context.getObjectToConvert();
|
T mapToConvert = context.getObjectToConvert();
|
||||||
return convertMap(mapToConvert);
|
return convertMap(mapToConvert, mapperRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BasicDBObject convertMap(Map mapToConvert) {
|
public static BasicDBObject convertMap(Map mapToConvert, MapperRegistry mapperRegistry) {
|
||||||
BasicDBObject dbObject = new BasicDBObject();
|
BasicDBObject dbObject = new BasicDBObject();
|
||||||
Set<Map.Entry> entries = mapToConvert.entrySet();
|
Set<Map.Entry> entries = mapToConvert.entrySet();
|
||||||
for (Map.Entry entry : entries) {
|
for (Map.Entry entry : entries) {
|
||||||
String key = (String)entry.getKey();
|
String key = (String)entry.getKey();
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
|
|
||||||
|
Object dbValue = mapperRegistry==null ? entry.getValue() : mapperRegistry.convertApplicationObjectToDBObject(value, Object.class);
|
||||||
|
|
||||||
if (key.contains(".")) {
|
if (key.contains(".")) {
|
||||||
key = key.replaceAll("\\.", DOT_PLACEHOLDER);
|
key = key.replaceAll("\\.", DOT_PLACEHOLDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbObject.put(key, value);
|
dbObject.put(key, dbValue);
|
||||||
}
|
}
|
||||||
return dbObject;
|
return dbObject;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Connections Parent</name>
|
<name>Connections Parent</name>
|
||||||
<description/>
|
<description/>
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
<module>jpa</module>
|
<module>jpa</module>
|
||||||
<module>jpa-liquibase</module>
|
<module>jpa-liquibase</module>
|
||||||
<module>infinispan</module>
|
<module>infinispan</module>
|
||||||
<module>mongo</module>
|
<!--<module>mongo</module>-->
|
||||||
<module>file</module>
|
<module>file</module>
|
||||||
<module>mongo-update</module>
|
<!--<module>mongo-update</module>-->
|
||||||
<module>http-client</module>
|
<module>http-client</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class AbstractOAuthClient {
|
|||||||
private final AtomicLong counter = new AtomicLong();
|
private final AtomicLong counter = new AtomicLong();
|
||||||
|
|
||||||
protected String clientId;
|
protected String clientId;
|
||||||
protected Map<String, String> credentials;
|
protected Map<String, Object> credentials;
|
||||||
protected String authUrl;
|
protected String authUrl;
|
||||||
protected String tokenUrl;
|
protected String tokenUrl;
|
||||||
protected RelativeUrlsUsed relativeUrlsUsed;
|
protected RelativeUrlsUsed relativeUrlsUsed;
|
||||||
@@ -37,11 +37,11 @@ public class AbstractOAuthClient {
|
|||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getCredentials() {
|
public Map<String, Object> getCredentials() {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCredentials(Map<String, String> credentials) {
|
public void setCredentials(Map<String, Object> credentials) {
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,15 @@ public interface OAuth2Constants {
|
|||||||
|
|
||||||
String PASSWORD = "password";
|
String PASSWORD = "password";
|
||||||
|
|
||||||
|
String CLIENT_CREDENTIALS = "client_credentials";
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/draft-ietf-oauth-assertions-01#page-5
|
||||||
|
String CLIENT_ASSERTION_TYPE = "client_assertion_type";
|
||||||
|
String CLIENT_ASSERTION = "client_assertion";
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/draft-jones-oauth-jwt-bearer-03#section-2.2
|
||||||
|
String CLIENT_ASSERTION_TYPE_JWT = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.keycloak;
|
package org.keycloak;
|
||||||
|
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -28,6 +29,9 @@ public class Version {
|
|||||||
VERSION = props.getProperty("version");
|
VERSION = props.getProperty("version");
|
||||||
BUILD_TIME = props.getProperty("build-time");
|
BUILD_TIME = props.getProperty("build-time");
|
||||||
RESOURCES_VERSION = VERSION.toLowerCase();
|
RESOURCES_VERSION = VERSION.toLowerCase();
|
||||||
|
if (RESOURCES_VERSION.endsWith("-snapshot")) {
|
||||||
|
RESOURCES_VERSION = RESOURCES_VERSION.replace("-snapshot", "-" + Time.currentTime());
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
VERSION=UNKNOWN;
|
VERSION=UNKNOWN;
|
||||||
BUILD_TIME=UNKNOWN;
|
BUILD_TIME=UNKNOWN;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package org.keycloak.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public interface ServiceAccountConstants {
|
||||||
|
|
||||||
|
String CLIENT_AUTH = "client_auth";
|
||||||
|
|
||||||
|
String SERVICE_ACCOUNT_USER_PREFIX = "service-account-";
|
||||||
|
|
||||||
|
String CLIENT_ID_PROTOCOL_MAPPER = "Client ID";
|
||||||
|
String CLIENT_HOST_PROTOCOL_MAPPER = "Client Host";
|
||||||
|
String CLIENT_ADDRESS_PROTOCOL_MAPPER = "Client IP Address";
|
||||||
|
String CLIENT_ID = "clientId";
|
||||||
|
String CLIENT_HOST = "clientHost";
|
||||||
|
String CLIENT_ADDRESS = "clientAddress";
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,8 +14,6 @@ public enum SslRequired {
|
|||||||
EXTERNAL,
|
EXTERNAL,
|
||||||
NONE;
|
NONE;
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public boolean isRequired(ClientConnection connection) {
|
public boolean isRequired(ClientConnection connection) {
|
||||||
return isRequired(connection.getRemoteAddr());
|
return isRequired(connection.getRemoteAddr());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.keycloak.jose.jws;
|
package org.keycloak.jose.jws;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
@@ -11,6 +12,7 @@ import java.io.Serializable;
|
|||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class JWSHeader implements Serializable {
|
public class JWSHeader implements Serializable {
|
||||||
@JsonProperty("alg")
|
@JsonProperty("alg")
|
||||||
private Algorithm algorithm;
|
private Algorithm algorithm;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class HMACProvider implements SignatureProvider {
|
|||||||
|
|
||||||
public static boolean verify(JWSInput input, SecretKey key) {
|
public static boolean verify(JWSInput input, SecretKey key) {
|
||||||
try {
|
try {
|
||||||
byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), key);
|
byte[] signature = sign(input.getEncodedSignatureInput().getBytes("UTF-8"), input.getHeader().getAlgorithm(), key);
|
||||||
String x = Base64Url.encode(signature);
|
String x = Base64Url.encode(signature);
|
||||||
return x.equals(input.getEncodedSignature());
|
return x.equals(input.getEncodedSignature());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.keycloak.json;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonNode;
|
||||||
|
import org.codehaus.jackson.JsonParser;
|
||||||
|
import org.codehaus.jackson.JsonProcessingException;
|
||||||
|
import org.codehaus.jackson.map.DeserializationContext;
|
||||||
|
import org.codehaus.jackson.map.JsonDeserializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
public class StringOrArrayDeserializer extends JsonDeserializer<Object> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
|
||||||
|
JsonNode jsonNode = jsonParser.readValueAsTree();
|
||||||
|
if (jsonNode.isArray()) {
|
||||||
|
ArrayList<String> a = new ArrayList<>(1);
|
||||||
|
Iterator<JsonNode> itr = jsonNode.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
a.add(itr.next().getTextValue());
|
||||||
|
}
|
||||||
|
return a.toArray(new String[a.size()]);
|
||||||
|
} else {
|
||||||
|
return new String[] { jsonNode.getTextValue() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.keycloak.json;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonGenerator;
|
||||||
|
import org.codehaus.jackson.map.JsonSerializer;
|
||||||
|
import org.codehaus.jackson.map.SerializerProvider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class StringOrArraySerializer extends JsonSerializer<Object> {
|
||||||
|
@Override
|
||||||
|
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
|
||||||
|
String[] array = (String[]) o;
|
||||||
|
if (array == null) {
|
||||||
|
jsonGenerator.writeNull();
|
||||||
|
} else if (array.length == 1) {
|
||||||
|
jsonGenerator.writeString(array[0]);
|
||||||
|
} else {
|
||||||
|
jsonGenerator.writeStartArray();
|
||||||
|
for (String s : array) {
|
||||||
|
jsonGenerator.writeString(s);
|
||||||
|
}
|
||||||
|
jsonGenerator.writeEndArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -163,11 +163,6 @@ public class AccessToken extends IDToken {
|
|||||||
return (AccessToken) super.issuer(issuer);
|
return (AccessToken) super.issuer(issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AccessToken audience(String audience) {
|
|
||||||
return (AccessToken) super.audience(audience);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessToken subject(String subject) {
|
public AccessToken subject(String subject) {
|
||||||
return (AccessToken) super.subject(subject);
|
return (AccessToken) super.subject(subject);
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
package org.keycloak.representations;
|
package org.keycloak.representations;
|
||||||
|
|
||||||
import org.codehaus.jackson.annotate.JsonAnyGetter;
|
|
||||||
import org.codehaus.jackson.annotate.JsonAnySetter;
|
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.codehaus.jackson.annotate.JsonUnwrapped;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import org.codehaus.jackson.annotate.JsonAnyGetter;
|
|||||||
import org.codehaus.jackson.annotate.JsonAnySetter;
|
import org.codehaus.jackson.annotate.JsonAnySetter;
|
||||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
|
import org.codehaus.jackson.map.annotate.JsonDeserialize;
|
||||||
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
|
import org.keycloak.json.StringOrArrayDeserializer;
|
||||||
|
import org.keycloak.json.StringOrArraySerializer;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -26,14 +30,16 @@ public class JsonWebToken implements Serializable {
|
|||||||
@JsonProperty("iss")
|
@JsonProperty("iss")
|
||||||
protected String issuer;
|
protected String issuer;
|
||||||
@JsonProperty("aud")
|
@JsonProperty("aud")
|
||||||
protected String audience;
|
@JsonSerialize(using = StringOrArraySerializer.class)
|
||||||
|
@JsonDeserialize(using = StringOrArrayDeserializer.class)
|
||||||
|
protected String[] audience;
|
||||||
@JsonProperty("sub")
|
@JsonProperty("sub")
|
||||||
protected String subject;
|
protected String subject;
|
||||||
@JsonProperty("typ")
|
@JsonProperty("typ")
|
||||||
protected String type;
|
protected String type;
|
||||||
@JsonProperty("azp")
|
@JsonProperty("azp")
|
||||||
public String issuedFor;
|
public String issuedFor;
|
||||||
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
protected Map<String, Object> otherClaims = new HashMap<>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@@ -72,7 +78,6 @@ public class JsonWebToken implements Serializable {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public boolean isNotBefore() {
|
public boolean isNotBefore() {
|
||||||
return Time.currentTime() >= notBefore;
|
return Time.currentTime() >= notBefore;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,12 +118,21 @@ public class JsonWebToken implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
public String getAudience() {
|
public String[] getAudience() {
|
||||||
return audience;
|
return audience;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonWebToken audience(String audience) {
|
public boolean hasAudience(String audience) {
|
||||||
|
for (String a : this.audience) {
|
||||||
|
if (a.equals(audience)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonWebToken audience(String... audience) {
|
||||||
this.audience = audience;
|
this.audience = audience;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -39,7 +39,7 @@ public class BaseAdapterConfig extends BaseRealmConfig {
|
|||||||
@JsonProperty("public-client")
|
@JsonProperty("public-client")
|
||||||
protected boolean publicClient;
|
protected boolean publicClient;
|
||||||
@JsonProperty("credentials")
|
@JsonProperty("credentials")
|
||||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
protected Map<String, Object> credentials = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public boolean isUseResourceRoleMappings() {
|
public boolean isUseResourceRoleMappings() {
|
||||||
@@ -114,11 +114,11 @@ public class BaseAdapterConfig extends BaseRealmConfig {
|
|||||||
this.enableBasicAuth = enableBasicAuth;
|
this.enableBasicAuth = enableBasicAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getCredentials() {
|
public Map<String, Object> getCredentials() {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCredentials(Map<String, String> credentials) {
|
public void setCredentials(Map<String, Object> credentials) {
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Executable
+87
@@ -0,0 +1,87 @@
|
|||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationExecutionRepresentation implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String authenticatorConfig;
|
||||||
|
private String authenticator;
|
||||||
|
private String flowAlias;
|
||||||
|
private boolean autheticatorFlow;
|
||||||
|
private String requirement;
|
||||||
|
private boolean userSetupAllowed;
|
||||||
|
private int priority;
|
||||||
|
|
||||||
|
public String getAuthenticatorConfig() {
|
||||||
|
return authenticatorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticatorConfig(String authenticatorConfig) {
|
||||||
|
this.authenticatorConfig = authenticatorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthenticator() {
|
||||||
|
return authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticator(String authenticator) {
|
||||||
|
this.authenticator = authenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequirement() {
|
||||||
|
return requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequirement(String requirement) {
|
||||||
|
this.requirement = requirement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPriority(int priority) {
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserSetupAllowed() {
|
||||||
|
return userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserSetupAllowed(boolean userSetupAllowed) {
|
||||||
|
this.userSetupAllowed = userSetupAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this execution is a flow, this is the flowId pointing to an AuthenticationFlowModel
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getFlowAlias() {
|
||||||
|
return flowAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlowAlias(String flowId) {
|
||||||
|
this.flowAlias = flowId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the referenced authenticator a flow?
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isAutheticatorFlow() {
|
||||||
|
return autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutheticatorFlow(boolean autheticatorFlow) {
|
||||||
|
this.autheticatorFlow = autheticatorFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Executable
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticationFlowRepresentation implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
private String description;
|
||||||
|
private String providerId;
|
||||||
|
private boolean topLevel;
|
||||||
|
private boolean builtIn;
|
||||||
|
protected List<AuthenticationExecutionRepresentation> authenticationExecutions;
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTopLevel() {
|
||||||
|
return topLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTopLevel(boolean topLevel) {
|
||||||
|
this.topLevel = topLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBuiltIn() {
|
||||||
|
return builtIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBuiltIn(boolean builtIn) {
|
||||||
|
this.builtIn = builtIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuthenticationExecutionRepresentation> getAuthenticationExecutions() {
|
||||||
|
return authenticationExecutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationExecutions(List<AuthenticationExecutionRepresentation> authenticationExecutions) {
|
||||||
|
this.authenticationExecutions = authenticationExecutions;
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AuthenticatorConfigRepresentation implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
private Map<String, String> config = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PEM values of key and certificate
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class CertificateRepresentation {
|
||||||
|
|
||||||
|
protected String privateKey;
|
||||||
|
protected String certificate;
|
||||||
|
|
||||||
|
public String getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivateKey(String privateKey) {
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertificate() {
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertificate(String certificate) {
|
||||||
|
this.certificate = certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ public class ClientRepresentation {
|
|||||||
protected String baseUrl;
|
protected String baseUrl;
|
||||||
protected Boolean surrogateAuthRequired;
|
protected Boolean surrogateAuthRequired;
|
||||||
protected Boolean enabled;
|
protected Boolean enabled;
|
||||||
|
protected String clientAuthenticatorType;
|
||||||
protected String secret;
|
protected String secret;
|
||||||
protected String[] defaultRoles;
|
protected String[] defaultRoles;
|
||||||
protected List<String> redirectUris;
|
protected List<String> redirectUris;
|
||||||
@@ -22,6 +23,7 @@ public class ClientRepresentation {
|
|||||||
protected Integer notBefore;
|
protected Integer notBefore;
|
||||||
protected Boolean bearerOnly;
|
protected Boolean bearerOnly;
|
||||||
protected Boolean consentRequired;
|
protected Boolean consentRequired;
|
||||||
|
protected Boolean serviceAccountsEnabled;
|
||||||
protected Boolean directGrantsOnly;
|
protected Boolean directGrantsOnly;
|
||||||
protected Boolean publicClient;
|
protected Boolean publicClient;
|
||||||
protected Boolean frontchannelLogout;
|
protected Boolean frontchannelLogout;
|
||||||
@@ -88,6 +90,14 @@ public class ClientRepresentation {
|
|||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getClientAuthenticatorType() {
|
||||||
|
return clientAuthenticatorType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientAuthenticatorType(String clientAuthenticatorType) {
|
||||||
|
this.clientAuthenticatorType = clientAuthenticatorType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSecret() {
|
public String getSecret() {
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
@@ -144,6 +154,14 @@ public class ClientRepresentation {
|
|||||||
this.consentRequired = consentRequired;
|
this.consentRequired = consentRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isServiceAccountsEnabled() {
|
||||||
|
return serviceAccountsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceAccountsEnabled(Boolean serviceAccountsEnabled) {
|
||||||
|
this.serviceAccountsEnabled = serviceAccountsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public Boolean isDirectGrantsOnly() {
|
public Boolean isDirectGrantsOnly() {
|
||||||
return directGrantsOnly;
|
return directGrantsOnly;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public class CredentialRepresentation {
|
|||||||
public static final String PASSWORD = "password";
|
public static final String PASSWORD = "password";
|
||||||
public static final String PASSWORD_TOKEN = "password-token";
|
public static final String PASSWORD_TOKEN = "password-token";
|
||||||
public static final String TOTP = "totp";
|
public static final String TOTP = "totp";
|
||||||
|
public static final String HOTP = "hotp";
|
||||||
public static final String CLIENT_CERT = "cert";
|
public static final String CLIENT_CERT = "cert";
|
||||||
public static final String KERBEROS = "kerberos";
|
public static final String KERBEROS = "kerberos";
|
||||||
|
|
||||||
@@ -22,6 +23,11 @@ public class CredentialRepresentation {
|
|||||||
protected String hashedSaltedValue;
|
protected String hashedSaltedValue;
|
||||||
protected String salt;
|
protected String salt;
|
||||||
protected Integer hashIterations;
|
protected Integer hashIterations;
|
||||||
|
protected Integer counter;
|
||||||
|
private String algorithm;
|
||||||
|
private Integer digits;
|
||||||
|
private Integer period;
|
||||||
|
|
||||||
// only used when updating a credential. Might set required action
|
// only used when updating a credential. Might set required action
|
||||||
protected boolean temporary;
|
protected boolean temporary;
|
||||||
|
|
||||||
@@ -80,4 +86,36 @@ public class CredentialRepresentation {
|
|||||||
public void setTemporary(boolean temporary) {
|
public void setTemporary(boolean temporary) {
|
||||||
this.temporary = temporary;
|
this.temporary = temporary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getCounter() {
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCounter(Integer counter) {
|
||||||
|
this.counter = counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlgorithm(String algorithm) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDigits() {
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDigits(Integer digits) {
|
||||||
|
this.digits = digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPeriod() {
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPeriod(Integer period) {
|
||||||
|
this.period = period;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -46,8 +46,16 @@ public class RealmRepresentation {
|
|||||||
protected String codeSecret;
|
protected String codeSecret;
|
||||||
protected RolesRepresentation roles;
|
protected RolesRepresentation roles;
|
||||||
protected List<String> defaultRoles;
|
protected List<String> defaultRoles;
|
||||||
|
@Deprecated
|
||||||
protected Set<String> requiredCredentials;
|
protected Set<String> requiredCredentials;
|
||||||
protected String passwordPolicy;
|
protected String passwordPolicy;
|
||||||
|
protected String otpPolicyType;
|
||||||
|
protected String otpPolicyAlgorithm;
|
||||||
|
protected Integer otpPolicyInitialCounter;
|
||||||
|
protected Integer otpPolicyDigits;
|
||||||
|
protected Integer otpPolicyLookAheadWindow;
|
||||||
|
protected Integer otpPolicyPeriod;
|
||||||
|
|
||||||
protected List<UserRepresentation> users;
|
protected List<UserRepresentation> users;
|
||||||
protected List<ScopeMappingRepresentation> scopeMappings;
|
protected List<ScopeMappingRepresentation> scopeMappings;
|
||||||
protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
|
protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
|
||||||
@@ -76,6 +84,14 @@ public class RealmRepresentation {
|
|||||||
protected Boolean internationalizationEnabled;
|
protected Boolean internationalizationEnabled;
|
||||||
protected Set<String> supportedLocales;
|
protected Set<String> supportedLocales;
|
||||||
protected String defaultLocale;
|
protected String defaultLocale;
|
||||||
|
protected List<AuthenticationFlowRepresentation> authenticationFlows;
|
||||||
|
protected List<AuthenticatorConfigRepresentation> authenticatorConfig;
|
||||||
|
protected List<RequiredActionProviderRepresentation> requiredActions;
|
||||||
|
protected String browserFlow;
|
||||||
|
protected String registrationFlow;
|
||||||
|
protected String directGrantFlow;
|
||||||
|
protected String resetCredentialsFlow;
|
||||||
|
protected String clientAuthenticationFlow;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected Boolean social;
|
protected Boolean social;
|
||||||
@@ -185,11 +201,11 @@ public class RealmRepresentation {
|
|||||||
scopeMappings.add(mapping);
|
scopeMappings.add(mapping);
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
@Deprecated
|
||||||
public Set<String> getRequiredCredentials() {
|
public Set<String> getRequiredCredentials() {
|
||||||
return requiredCredentials;
|
return requiredCredentials;
|
||||||
}
|
}
|
||||||
|
@Deprecated
|
||||||
public void setRequiredCredentials(Set<String> requiredCredentials) {
|
public void setRequiredCredentials(Set<String> requiredCredentials) {
|
||||||
this.requiredCredentials = requiredCredentials;
|
this.requiredCredentials = requiredCredentials;
|
||||||
}
|
}
|
||||||
@@ -626,5 +642,115 @@ public class RealmRepresentation {
|
|||||||
identityProviderMappers.add(rep);
|
identityProviderMappers.add(rep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AuthenticationFlowRepresentation> getAuthenticationFlows() {
|
||||||
|
return authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticationFlows(List<AuthenticationFlowRepresentation> authenticationFlows) {
|
||||||
|
this.authenticationFlows = authenticationFlows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AuthenticatorConfigRepresentation> getAuthenticatorConfig() {
|
||||||
|
return authenticatorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticatorConfig(List<AuthenticatorConfigRepresentation> authenticatorConfig) {
|
||||||
|
this.authenticatorConfig = authenticatorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RequiredActionProviderRepresentation> getRequiredActions() {
|
||||||
|
return requiredActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequiredActions(List<RequiredActionProviderRepresentation> requiredActions) {
|
||||||
|
this.requiredActions = requiredActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOtpPolicyType() {
|
||||||
|
return otpPolicyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyType(String otpPolicyType) {
|
||||||
|
this.otpPolicyType = otpPolicyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOtpPolicyAlgorithm() {
|
||||||
|
return otpPolicyAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyAlgorithm(String otpPolicyAlgorithm) {
|
||||||
|
this.otpPolicyAlgorithm = otpPolicyAlgorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOtpPolicyInitialCounter() {
|
||||||
|
return otpPolicyInitialCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyInitialCounter(Integer otpPolicyInitialCounter) {
|
||||||
|
this.otpPolicyInitialCounter = otpPolicyInitialCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOtpPolicyDigits() {
|
||||||
|
return otpPolicyDigits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyDigits(Integer otpPolicyDigits) {
|
||||||
|
this.otpPolicyDigits = otpPolicyDigits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOtpPolicyLookAheadWindow() {
|
||||||
|
return otpPolicyLookAheadWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyLookAheadWindow(Integer otpPolicyLookAheadWindow) {
|
||||||
|
this.otpPolicyLookAheadWindow = otpPolicyLookAheadWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getOtpPolicyPeriod() {
|
||||||
|
return otpPolicyPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOtpPolicyPeriod(Integer otpPolicyPeriod) {
|
||||||
|
this.otpPolicyPeriod = otpPolicyPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrowserFlow() {
|
||||||
|
return browserFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrowserFlow(String browserFlow) {
|
||||||
|
this.browserFlow = browserFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegistrationFlow() {
|
||||||
|
return registrationFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegistrationFlow(String registrationFlow) {
|
||||||
|
this.registrationFlow = registrationFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDirectGrantFlow() {
|
||||||
|
return directGrantFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDirectGrantFlow(String directGrantFlow) {
|
||||||
|
this.directGrantFlow = directGrantFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResetCredentialsFlow() {
|
||||||
|
return resetCredentialsFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetCredentialsFlow(String resetCredentialsFlow) {
|
||||||
|
this.resetCredentialsFlow = resetCredentialsFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientAuthenticationFlow() {
|
||||||
|
return clientAuthenticationFlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientAuthenticationFlow(String clientAuthenticationFlow) {
|
||||||
|
this.clientAuthenticationFlow = clientAuthenticationFlow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Executable
+73
@@ -0,0 +1,73 @@
|
|||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class RequiredActionProviderRepresentation {
|
||||||
|
|
||||||
|
private String alias;
|
||||||
|
private String name;
|
||||||
|
private String providerId;
|
||||||
|
private boolean enabled;
|
||||||
|
private boolean defaultAction;
|
||||||
|
private Map<String, String> config = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for display purposes. Probably should clean this code up and make alias and name the same, but
|
||||||
|
* the old code references an Enum and the admin console creates a "friendly" name for each enum.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDefaultAction() {
|
||||||
|
return defaultAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultAction(boolean defaultAction) {
|
||||||
|
this.defaultAction = defaultAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProviderId() {
|
||||||
|
return providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProviderId(String providerId) {
|
||||||
|
this.providerId = providerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
package org.keycloak.representations.idm;
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
|
import org.keycloak.util.MultivaluedHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
@@ -13,6 +17,7 @@ public class UserRepresentation {
|
|||||||
|
|
||||||
protected String self; // link
|
protected String self; // link
|
||||||
protected String id;
|
protected String id;
|
||||||
|
protected Long createdTimestamp;
|
||||||
protected String username;
|
protected String username;
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
protected boolean totp;
|
protected boolean totp;
|
||||||
@@ -21,7 +26,10 @@ public class UserRepresentation {
|
|||||||
protected String lastName;
|
protected String lastName;
|
||||||
protected String email;
|
protected String email;
|
||||||
protected String federationLink;
|
protected String federationLink;
|
||||||
protected Map<String, String> attributes;
|
protected String serviceAccountClientId; // For rep, it points to clientId (not DB ID)
|
||||||
|
|
||||||
|
// Currently there is Map<String, List<String>> but for backwards compatibility, we also need to support Map<String, String>
|
||||||
|
protected Map<String, Object> attributes;
|
||||||
protected List<CredentialRepresentation> credentials;
|
protected List<CredentialRepresentation> credentials;
|
||||||
protected List<String> requiredActions;
|
protected List<String> requiredActions;
|
||||||
protected List<FederatedIdentityRepresentation> federatedIdentities;
|
protected List<FederatedIdentityRepresentation> federatedIdentities;
|
||||||
@@ -50,6 +58,14 @@ public class UserRepresentation {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getCreatedTimestamp() {
|
||||||
|
return createdTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedTimestamp(Long createdTimestamp) {
|
||||||
|
this.createdTimestamp = createdTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
public String getFirstName() {
|
||||||
return firstName;
|
return firstName;
|
||||||
}
|
}
|
||||||
@@ -106,17 +122,23 @@ public class UserRepresentation {
|
|||||||
this.emailVerified = emailVerified;
|
this.emailVerified = emailVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getAttributes() {
|
public Map<String, Object> getAttributes() {
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttributes(Map<String, String> attributes) {
|
// This method can be removed once we can remove backwards compatibility with Keycloak 1.3 (then getAttributes() can be changed to return Map<String, List<String>> )
|
||||||
|
@JsonIgnore
|
||||||
|
public Map<String, List<String>> getAttributesAsListValues() {
|
||||||
|
return (Map) attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributes(Map<String, Object> attributes) {
|
||||||
this.attributes = attributes;
|
this.attributes = attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserRepresentation attribute(String name, String value) {
|
public UserRepresentation singleAttribute(String name, String value) {
|
||||||
if (this.attributes == null) attributes = new HashMap<String, String>();
|
if (this.attributes == null) attributes = new HashMap<>();
|
||||||
attributes.put(name, value);
|
attributes.put(name, Arrays.asList(value));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,15 +150,6 @@ public class UserRepresentation {
|
|||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserRepresentation credential(String type, String value) {
|
|
||||||
if (this.credentials == null) credentials = new ArrayList<CredentialRepresentation>();
|
|
||||||
CredentialRepresentation cred = new CredentialRepresentation();
|
|
||||||
cred.setType(type);
|
|
||||||
cred.setValue(value);
|
|
||||||
credentials.add(cred);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getRequiredActions() {
|
public List<String> getRequiredActions() {
|
||||||
return requiredActions;
|
return requiredActions;
|
||||||
}
|
}
|
||||||
@@ -197,4 +210,12 @@ public class UserRepresentation {
|
|||||||
public void setFederationLink(String federationLink) {
|
public void setFederationLink(String federationLink) {
|
||||||
this.federationLink = federationLink;
|
this.federationLink = federationLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServiceAccountClientId() {
|
||||||
|
return serviceAccountClientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceAccountClientId(String serviceAccountClientId) {
|
||||||
|
this.serviceAccountClientId = serviceAccountClientId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,8 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class UserSessionRepresentation {
|
public class UserSessionRepresentation {
|
||||||
private String id;
|
private String id;
|
||||||
private String user;
|
private String username;
|
||||||
|
private String userId;
|
||||||
private String ipAddress;
|
private String ipAddress;
|
||||||
private long start;
|
private long start;
|
||||||
private long lastAccess;
|
private long lastAccess;
|
||||||
@@ -25,12 +26,20 @@ public class UserSessionRepresentation {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUser() {
|
public String getUsername() {
|
||||||
return user;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUser(String user) {
|
public void setUsername(String username) {
|
||||||
this.user = user;
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getIpAddress() {
|
public String getIpAddress() {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.keycloak.util;
|
|||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.codehaus.jackson.map.SerializationConfig;
|
import org.codehaus.jackson.map.SerializationConfig;
|
||||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||||
import org.codehaus.jackson.type.TypeReference;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
|
||||||
import org.keycloak.constants.GenericConstants;
|
import org.keycloak.constants.GenericConstants;
|
||||||
|
|
||||||
@@ -12,6 +13,14 @@ import org.keycloak.constants.GenericConstants;
|
|||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class KeystoreUtil {
|
public class KeystoreUtil {
|
||||||
|
static {
|
||||||
|
BouncyIntegration.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum KeystoreFormat {
|
||||||
|
JKS,
|
||||||
|
PKCS12
|
||||||
|
}
|
||||||
|
|
||||||
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
|
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
@@ -22,4 +31,26 @@ public class KeystoreUtil {
|
|||||||
trustStream.close();
|
trustStream.close();
|
||||||
return trustStore;
|
return trustStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PrivateKey loadPrivateKeyFromKeystore(String keystoreFile, String storePassword, String keyPassword, String keyAlias, KeystoreFormat format) {
|
||||||
|
InputStream stream = FindFile.findFile(keystoreFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
KeyStore keyStore = null;
|
||||||
|
if (format == KeystoreFormat.JKS) {
|
||||||
|
keyStore = KeyStore.getInstance(format.toString());
|
||||||
|
} else {
|
||||||
|
keyStore = KeyStore.getInstance(format.toString(), "BC");
|
||||||
|
}
|
||||||
|
|
||||||
|
keyStore.load(stream, storePassword.toCharArray());
|
||||||
|
PrivateKey key = (PrivateKey) keyStore.getKey(keyAlias, keyPassword.toCharArray());
|
||||||
|
if (key == null) {
|
||||||
|
throw new RuntimeException("Couldn't load key with alias '" + keyAlias + "' from keystore");
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Failed to load private key: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -96,6 +96,7 @@ public class RSAVerifierTest {
|
|||||||
String encoded = new JWSBuilder()
|
String encoded = new JWSBuilder()
|
||||||
.jsonContent(token)
|
.jsonContent(token)
|
||||||
.rsa256(idpPair.getPrivate());
|
.rsa256(idpPair.getPrivate());
|
||||||
|
System.out.print("encoded size: " + encoded.length());
|
||||||
AccessToken token = verifySkeletonKeyToken(encoded);
|
AccessToken token = verifySkeletonKeyToken(encoded);
|
||||||
Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
|
Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
|
||||||
Assert.assertEquals("CN=Client", token.getSubject());
|
Assert.assertEquals("CN=Client", token.getSubject());
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package org.keycloak.jose;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.jose.jws.JWSBuilder;
|
||||||
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
|
import org.keycloak.jose.jws.crypto.HMACProvider;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class HmacTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHmacSignatures() throws Exception {
|
||||||
|
SecretKey secret = new SecretKeySpec(UUID.randomUUID().toString().getBytes(), "HmacSHA256");
|
||||||
|
String encoded = new JWSBuilder().content("12345678901234567890".getBytes())
|
||||||
|
.hmac256(secret);
|
||||||
|
System.out.println("length: " + encoded.length());
|
||||||
|
JWSInput input = new JWSInput(encoded);
|
||||||
|
Assert.assertTrue(HMACProvider.verify(input, secret));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package org.keycloak.jose;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.representations.JsonWebToken;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by st on 20.08.15.
|
||||||
|
*/
|
||||||
|
public class JsonWebTokenTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAudSingle() throws IOException {
|
||||||
|
String single = "{ \"aud\": \"test\" }";
|
||||||
|
JsonWebToken s = JsonSerialization.readValue(single, JsonWebToken.class);
|
||||||
|
assertArrayEquals(new String[] { "test" }, s.getAudience());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAudArray() throws IOException {
|
||||||
|
String single = "{ \"aud\": [\"test\"] }";
|
||||||
|
JsonWebToken s = JsonSerialization.readValue(single, JsonWebToken.class);
|
||||||
|
assertArrayEquals(new String[]{"test"}, s.getAudience());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws IOException {
|
||||||
|
JsonWebToken jsonWebToken = new JsonWebToken();
|
||||||
|
jsonWebToken.audience("test");
|
||||||
|
assertTrue(JsonSerialization.writeValueAsPrettyString(jsonWebToken).contains("\"aud\" : \"test\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testArray() throws IOException {
|
||||||
|
JsonWebToken jsonWebToken = new JsonWebToken();
|
||||||
|
jsonWebToken.audience("test", "test2");
|
||||||
|
assertTrue(JsonSerialization.writeValueAsPrettyString(jsonWebToken).contains("\"aud\" : [ \"test\", \"test2\" ]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
Vendored
+3
-15
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -40,18 +40,6 @@
|
|||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-model-file</artifactId>
|
<artifactId>keycloak-model-file</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-sessions-mem</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-sessions-jpa</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-sessions-mongo</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-model-sessions-infinispan</artifactId>
|
<artifactId>keycloak-model-sessions-infinispan</artifactId>
|
||||||
@@ -132,7 +120,7 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- mongo -->
|
<!-- mongo -->
|
||||||
<dependency>
|
<!-- <dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-connections-mongo</artifactId>
|
<artifactId>keycloak-connections-mongo</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -151,7 +139,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mongodb</groupId>
|
<groupId>org.mongodb</groupId>
|
||||||
<artifactId>mongo-java-driver</artifactId>
|
<artifactId>mongo-java-driver</artifactId>
|
||||||
</dependency>
|
</dependency> -->
|
||||||
|
|
||||||
<!-- export/import -->
|
<!-- export/import -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -27,4 +27,10 @@
|
|||||||
<outputDirectory>modules</outputDirectory>
|
<outputDirectory>modules</outputDirectory>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>../../shared-cli/adapter-install.cli</source>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
</assembly>
|
</assembly>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
-3
@@ -23,9 +23,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-subsystem">
|
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-subsystem">
|
||||||
<properties>
|
|
||||||
<property name="keycloak-version" value="${project.version}"/>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<resource-root path="."/>
|
<resource-root path="."/>
|
||||||
|
|||||||
@@ -27,4 +27,10 @@
|
|||||||
<outputDirectory>modules/system/layers/base</outputDirectory>
|
<outputDirectory>modules/system/layers/base</outputDirectory>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>../../shared-cli/adapter-install.cli</source>
|
||||||
|
<outputDirectory>bin</outputDirectory>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
</assembly>
|
</assembly>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak AS7 / JBoss EAP 6 Adapter Distros</name>
|
<name>Keycloak AS7 / JBoss EAP 6 Adapter Distros</name>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>1.3.1.Final</version>
|
<version>1.5.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 2567 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user