diff --git a/connector-rest-wordpress b/connector-rest-wordpress deleted file mode 160000 index ab7bc4c..0000000 --- a/connector-rest-wordpress +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ab7bc4c0a40024af5b0857f54a76070c00d15b71 diff --git a/connector-rest-wordpress/.gitignore b/connector-rest-wordpress/.gitignore new file mode 100644 index 0000000..829bbce --- /dev/null +++ b/connector-rest-wordpress/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target/ diff --git a/connector-rest-wordpress/LICENSE b/connector-rest-wordpress/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/connector-rest-wordpress/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/connector-rest-wordpress/README b/connector-rest-wordpress/README new file mode 100644 index 0000000..35d0973 --- /dev/null +++ b/connector-rest-wordpress/README @@ -0,0 +1,15 @@ +# A ConnId connector for Wordpress +# Supports create, update, schema, test +# search and delete operations for users. + +# search has not yet been tested, and +# several create and update error +# handling are a work in progress + +# Project is current appropriate for +# POC and testing, but not production +# use. It assumes Wordpress to use the +# JWT authentication plugin for the +# REST API https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api +# That plugin requires that the REST API +# is at /wp-json diff --git a/connector-rest-wordpress/connector-rest-wordpress.tar.2019-02-17 b/connector-rest-wordpress/connector-rest-wordpress.tar.2019-02-17 new file mode 100644 index 0000000..52808f8 Binary files /dev/null and b/connector-rest-wordpress/connector-rest-wordpress.tar.2019-02-17 differ diff --git a/connector-rest-wordpress/connector-rest-wordpress.tar.2019-03-13 b/connector-rest-wordpress/connector-rest-wordpress.tar.2019-03-13 new file mode 100644 index 0000000..dc91335 Binary files /dev/null and b/connector-rest-wordpress/connector-rest-wordpress.tar.2019-03-13 differ diff --git a/connector-rest-wordpress/pom.xml b/connector-rest-wordpress/pom.xml new file mode 100644 index 0000000..664fdea --- /dev/null +++ b/connector-rest-wordpress/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + + connector-parent + com.evolveum.polygon + 1.4.2.14 + + + + edu.unc.polygon + connector-rest-wordpress + .14-SNAPSHOT + jar + + Wordpress REST Connector + + + edu.unc.polygon.connector.wordpress + WordpressRestConnector + + + + + evolveum-nexus-releases + Internal Releases + http://nexus.evolveum.com/nexus/content/repositories/releases/ + + + evolveum-nexus-snapshots + Internal Releases + http://nexus.evolveum.com/nexus/content/repositories/snapshots/ + + + apache-snapshots + Apache Snapshots + http://repository.apache.org/snapshots/ + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + + + connector-rest + com.evolveum.polygon + 1.4.2.14-SNAPSHOT + + + org.json + json + 20180813 + + + + + + diff --git a/connector-rest-wordpress/samples/backup/connector-rest-wordpress.xml b/connector-rest-wordpress/samples/backup/connector-rest-wordpress.xml new file mode 100644 index 0000000..df69886 --- /dev/null +++ b/connector-rest-wordpress/samples/backup/connector-rest-wordpress.xml @@ -0,0 +1,262 @@ + + wordpress10 + + 2019-02-27T14:37:46.148Z + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T14:37:38.675Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000171 + + wordpress10 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T14:37:42.502Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000235 + + wordpress10 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T14:37:44.010Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000276 + + wordpress10 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T14:37:46.247Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000317 + + wordpress10 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + up + + + + + + c:connectorType + edu.unc.polygon.connector.wordpress.WordpressRestConnector + + + + + + + 54y6RxN7GfC7aes3 + id + http://wordpress_server/wp-json + password + username + admin + + + + + 2019-02-27T14:37:38.881Z + eabcca0492d13af9-cb61678d74c86efd + + + + + + + + + + + icfs:uid + icfs:name + icfs:name + icfs:name + MESSAGE_OBJECT_CLASS___ACCOUNT__ + + + + + + + 120 + password + + + + + + + 130 + username + + + + + + + ConnId Name + 110 + __NAME__ + + + + + + + 140 + id + + + + + + + 150 + email + + + + + + + + ConnId UID + 100 + read + + + + + + + + + + + account + default + true + ri:MESSAGE_OBJECT_CLASS___ACCOUNT__ + + ri:username + + + $user/name + + + + + ri:email + + + $user/emailAddress + + + + + icfs:name + + + $user/name + + + + + + + + + + + + + 2019-02-27T14:37:38.876Z + dec8f19649257694-abba027d4eec515 + + + + + + + + + + connector + + + + + + + true + + + true + + + true + + + true + + + true + + connector + + + + true + + + + + + diff --git a/connector-rest-wordpress/samples/connector-rest-wordpress.xml b/connector-rest-wordpress/samples/connector-rest-wordpress.xml new file mode 100644 index 0000000..606bd97 --- /dev/null +++ b/connector-rest-wordpress/samples/connector-rest-wordpress.xml @@ -0,0 +1,326 @@ + + wordpress15 + + 2019-03-19T13:02:44.112Z + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-03-19T13:02:35.004Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000168 + + wordpress15 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-03-19T13:02:39.309Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000232 + + wordpress15 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-03-19T13:02:41.338Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000273 + + wordpress15 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-03-19T13:02:44.233Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000314 + + wordpress15 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + up + + + + + c:connectorType + edu.unc.polygon.connector.wordpress.WordpressRestConnector + + + + + + + 54y6RxN7GfC7aes3 + true + id + http://wordpress_server/wp-json + password + username + admin + 1 + true + + + + + 2019-03-19T13:02:35.235Z + db5b306ee09fcbbd-63313e1ea25f76e9 + + + + + + + + + + + icfs:uid + icfs:name + icfs:name + icfs:name + MESSAGE_OBJECT_CLASS___ACCOUNT__ + + + + + + + 120 + password + + + + + + + 130 + roles + + + + + + + 140 + username + + + + + + + ConnId Name + 110 + __NAME__ + + + + + + + 150 + id + + + + + + + 160 + last_name + + + + + + + 170 + email + + + + + + + 180 + first_name + + + + + + + 190 + name + + + + + + + ConnId UID + 100 + read + + + + + + + + + + + account + default + true + ri:MESSAGE_OBJECT_CLASS___ACCOUNT__ + + ri:username + + + $user/name + + + + + ri:email + + + $user/emailAddress + + + + + ri:name + + + $user/fullName + + + + + ri:first_name + + + $user/givenName + + + + + ri:last_name + + + $user/familyName + + + + + icfs:name + + + $user/name + + + + + + + + + + + + + 2019-03-19T13:02:35.229Z + 2859b764880a952d-7fb0628b3129443b + + + + + + + + + + connector + + + + + false + + + + + true + + + true + + + true + + + true + + + true + + connector + + + + true + + + true + false + + + + + + diff --git a/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019-03-22 b/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019-03-22 new file mode 100644 index 0000000..0c108da --- /dev/null +++ b/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019-03-22 @@ -0,0 +1,308 @@ + + wordpress11 + + 2019-02-27T17:34:59.709Z + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T17:34:51.716Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000180 + + wordpress11 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T17:34:55.774Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000244 + + wordpress11 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T17:34:57.295Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000285 + + wordpress11 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-27T17:34:59.819Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000326 + + wordpress11 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + up + + + + + 54y6RxN7GfC7aes3 + id + http://wordpress_server/wp-json + password + username + admin + + + + + 2019-02-27T17:34:51.956Z + a2cdf44895930342-82281c17d5e27924 + + + + + + + + + + + icfs:uid + icfs:name + icfs:name + icfs:name + MESSAGE_OBJECT_CLASS___ACCOUNT__ + + + + + + + 120 + password + + + + + + + 130 + roles + + + + + + + 140 + username + + + + + + + ConnId Name + 110 + __NAME__ + + + + + + + 150 + id + + + + + + + 160 + last_name + + + + + + + 170 + email + + + + + + + 180 + first_name + + + + + + + 190 + name + + + + + + + ConnId UID + 100 + read + + + + + + + + + + + account + default + true + ri:MESSAGE_OBJECT_CLASS___ACCOUNT__ + + ri:username + + + $user/name + + + + + ri:email + + + $user/emailAddress + + + + + ri:name + + + $user/fullName + + + + + ri:first_name + + + $user/givenName + + + + + ri:last_name + + + $user/familyName + + + + + icfs:name + + + $user/name + + + + + + + + + + + + + 2019-02-27T17:34:51.950Z + b729a58a9e1701d1-b7fa31ba5db845f2 + + + + + + + + + + connector + + + + + + + true + + + true + + + true + + + true + + + true + + connector + + + + true + + + + + + diff --git a/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019.02-27 b/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019.02-27 new file mode 100644 index 0000000..ccf6c7b --- /dev/null +++ b/connector-rest-wordpress/samples/connector-rest-wordpress.xml.2019.02-27 @@ -0,0 +1,262 @@ + + wordpress2 + + 2019-02-26T13:47:17.404Z + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-26T13:46:23.011Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000270 + + wordpress2 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-26T13:46:25.508Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000311 + + wordpress2 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-26T13:46:29.184Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000352 + + wordpress2 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-26T13:46:35.665Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000428 + + wordpress2 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + 2019-02-26T13:47:17.462Z + + + modify + c:ResourceType + + + com.evolveum.midpoint.model.impl.lens.ChangeExecutor.executeDelta + success + 1000000000000000544 + + wordpress2 + + success + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + + + up + + + + + 54y6RxN7GfC7aes3 + id + http://wordpress_server/wp-json + password + username + admin + + + + + 2019-02-26T13:47:17.687Z + 3e81caa04edd051e-6991ea285dc7cd37 + + + + + + + + + + + icfs:uid + icfs:name + icfs:name + icfs:name + MESSAGE_OBJECT_CLASS___ACCOUNT__ + + + + + + + 120 + password + + + + + + + 130 + username + + + + + + + ConnId Name + 110 + __NAME__ + + + + + + + 140 + id + + + + + + + 150 + email + + + + + + + ConnId UID + 100 + read + + + + + + + + + + + account + default + true + ri:MESSAGE_OBJECT_CLASS___ACCOUNT__ + + ri:username + + + $user/name + + + + + ri:email + + + $user/emailAddress + + + + + + + + + + + + + 2019-02-26T13:47:17.686Z + dba87b27b95a9c73-8527ccc80dac2310 + + + + + + + + + + connector + + + + + + + true + + + true + + + true + + + true + + + true + + connector + + + + true + + + + + + diff --git a/connector-rest-wordpress/src/main/assembly/connector.xml b/connector-rest-wordpress/src/main/assembly/connector.xml new file mode 100644 index 0000000..efca6d1 --- /dev/null +++ b/connector-rest-wordpress/src/main/assembly/connector.xml @@ -0,0 +1,47 @@ + + + + + connector + + + jar + + + false + + + + target/classes + + + + + + + lib + false + runtime + + net.tirasa.connid:connector-framework + + + + \ No newline at end of file diff --git a/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilter.java b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilter.java new file mode 100644 index 0000000..6cdf4a6 --- /dev/null +++ b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilter.java @@ -0,0 +1,19 @@ +package edu.unc.polygon.connector.wordpress; + +/** + * + */ +public class WordpressFilter { + public String byName; + public String byUid; + public String byEmailAddress; + + @Override + public String toString() { + return "WordpressFilter{" + + "byName='" + byName + '\'' + + ", byUid=" + byUid + + ", byEmailAddress='" + byEmailAddress + '\'' + + '}'; + } +} diff --git a/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java new file mode 100644 index 0000000..80f55ae --- /dev/null +++ b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java @@ -0,0 +1,64 @@ +/* + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package edu.unc.polygon.connector.wordpress; + +import org.identityconnectors.common.logging.Log; +import org.identityconnectors.framework.common.objects.Attribute; +import org.identityconnectors.framework.common.objects.Name; +import org.identityconnectors.framework.common.objects.Uid; +import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; + +/** + */ +public class WordpressFilterTranslator extends AbstractFilterTranslator { + private static final Log LOG = Log.getLog(WordpressFilterTranslator.class); + + @Override + protected WordpressFilter createEqualsExpression(EqualsFilter filter, boolean not) { + LOG.ok("createEqualsExpression, filter: {0}, not: {1}", filter, not); + + if (not) { + return null; // not supported + } + + Attribute attr = filter.getAttribute(); + LOG.ok("attr.getName: {0}, attr.getValue: {1}, Uid.NAME: {2}, Name.NAME: {3}", attr.getName(), attr.getValue(), Uid.NAME, Name.NAME); + if (Uid.NAME.equals(attr.getName())) { + if (attr.getValue() != null && attr.getValue().get(0) != null) { + WordpressFilter lf = new WordpressFilter(); + lf.byUid = String.valueOf(attr.getValue().get(0)); + LOG.ok("lf.byUid: {0}, attr.getValue().get(0): {1}", lf.byUid, attr.getValue().get(0)); + return lf; + } + } + else if (Name.NAME.equals(attr.getName())) { + if (attr.getValue() != null && attr.getValue().get(0) != null) { + WordpressFilter lf = new WordpressFilter(); + lf.byName = String.valueOf(attr.getValue().get(0)); + return lf; + } + } + else if (WordpressRestConnector.ATTR_MAIL.equals(attr.getName())) { + if (attr.getValue() != null && attr.getValue().get(0) != null) { + WordpressFilter lf = new WordpressFilter(); + lf.byEmailAddress = String.valueOf(attr.getValue().get(0)); + return lf; + } + } + + return null; // not supported + } +} diff --git a/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java.2019-03-20 b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java.2019-03-20 new file mode 100644 index 0000000..efc55e9 --- /dev/null +++ b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressFilterTranslator.java.2019-03-20 @@ -0,0 +1,33 @@ +package edu.unc.polygon.connector.wordpress; + +import org.identityconnectors.framework.common.objects.Attribute; +import org.identityconnectors.framework.common.objects.Uid; +import org.identityconnectors.framework.common.objects.filter.AbstractFilterTranslator; +import org.identityconnectors.framework.common.objects.filter.EqualsFilter; + +import java.util.List; + +public class WordpressFilterTranslator extends AbstractFilterTranslator { + + @Override + protected String createEqualsExpression(EqualsFilter filter, boolean not) { + if (not) { + return null; + } + + Attribute attr = filter.getAttribute(); + if (!attr.is(Uid.NAME)) { + return null; + } + + List values = attr.getValue(); + if (values.isEmpty()) { + return null; + } + + Object value = values.get(0); + + return value != null ? value.toString() : null; + } +} + diff --git a/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConfiguration.java b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConfiguration.java new file mode 100644 index 0000000..a3ab632 --- /dev/null +++ b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConfiguration.java @@ -0,0 +1,127 @@ +/** + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package edu.unc.polygon.connector.wordpress; + +import com.evolveum.polygon.rest.AbstractRestConfiguration; +import org.identityconnectors.common.logging.Log; +import org.identityconnectors.framework.common.exceptions.ConfigurationException; +import org.identityconnectors.framework.common.objects.ObjectClass; +import org.identityconnectors.framework.spi.AbstractConfiguration; +import org.identityconnectors.framework.spi.ConfigurationProperty; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + + +/** + * @author ekromhout@gmail.com + * + */ +public class WordpressRestConfiguration extends AbstractRestConfiguration { + + private static final Log LOG = Log.getLog(WordpressRestConfiguration.class); + + private String WordpressRestUrl; + private String WordpressUsername; + private String WordpressPassword; + private String WordpressUniqueAttribute; + private String WordpressNameAttribute; + private String WordpressPasswordAttribute; + private boolean WordpressSoftUserDelete = true; + private Integer WordpressRecyclebinUser = 1; + + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_USERNAME", + helpMessageKey = "UI_WORDPRESS_USERNAME_HELP") + public String getWordpressUsername() { + return WordpressUsername; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_PASSWORD", + helpMessageKey = "UI_WORDPRESS_PASSWORD_HELP") + public String getWordpressPassword() { + return WordpressPassword; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_REST_URL", + helpMessageKey = "UI_WORDPRESS_REST_URL_HELP") + public String getWordpressRestUrl() { + return WordpressRestUrl; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_UNIQUE_ATTRIBUTE", + helpMessageKey = "UI_WORDPRESS_UNIQUE_ATTRIBUTE_HELP") + public String getWordpressUniqueAttribute() { + return WordpressUniqueAttribute; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_NAME_ATTRIBUTE", + helpMessageKey = "UI_WORDPRESS_NAME_ATTRIBUTE_HELP") + public String getWordpressNameAttribute() { + return WordpressNameAttribute; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_PASSWORD_ATTRIBUTE", + helpMessageKey = "UI_WORDPRESS_PASSWORD_ATTRIBUTE_HELP") + public String getWordpressPasswordAttribute() { + return WordpressPasswordAttribute; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_SOFT_USER_DELETE", + helpMessageKey = "UI_WORDPRESS_SOFT_USER_DELETE_HELP") + public boolean getWordpressSoftUserDelete() { + return WordpressSoftUserDelete; + } + @ConfigurationProperty( + displayMessageKey = "UI_WORDPRESS_RECYCLEBIN_USER", + helpMessageKey = "UI_WORDPRESS_RECYCLEBIN_USER_HELP") + public Integer getWordpressRecyclebinUser() { + return WordpressRecyclebinUser; + } + + + public void setWordpressUsername(String WordpressUsername) { + this.WordpressUsername = WordpressUsername; + } + public void setWordpressPassword(String WordpressPassword) { + this.WordpressPassword = WordpressPassword; + } + public void setWordpressRestUrl(String WordpressRestUrl) { + this.WordpressRestUrl = WordpressRestUrl; + } + public void setWordpressUniqueAttribute(String WordpressUniqueAttribute) { + this.WordpressUniqueAttribute = WordpressUniqueAttribute; + } + public void setWordpressNameAttribute(String WordpressNameAttribute) { + this.WordpressNameAttribute = WordpressNameAttribute; + } + public void setWordpressPasswordAttribute(String WordpressPasswordAttribute) { + this.WordpressPasswordAttribute = WordpressPasswordAttribute; + } + public void setWordpressSoftUserDelete(boolean WordpressSoftUserDelete) { + this.WordpressSoftUserDelete = WordpressSoftUserDelete; + } + public void setWordpressRecyclebinUser(Integer WordpressRecyclebinUser) { + this.WordpressRecyclebinUser = WordpressRecyclebinUser; + } + + @Override + public void validate() { + // TODO + } + +} diff --git a/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConnector.java b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConnector.java new file mode 100644 index 0000000..af30e53 --- /dev/null +++ b/connector-rest-wordpress/src/main/java/edu/unc/polygon/connector/wordpress/WordpressRestConnector.java @@ -0,0 +1,675 @@ +/** + * Copyright (c) 2016 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package edu.unc.polygon.connector.wordpress; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.HttpEntity; +import org.apache.http.HttpRequest; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.apache.http.entity.StringEntity; +import org.apache.http.auth.AuthenticationException; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.client.methods.*; +import org.apache.http.annotation.NotThreadSafe; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONException; +import org.identityconnectors.common.Base64; +import org.identityconnectors.common.StringUtil; +import org.identityconnectors.framework.common.objects.ObjectClassInfoBuilder; +import org.identityconnectors.framework.common.objects.Schema; +import org.identityconnectors.framework.common.objects.SchemaBuilder; +import org.identityconnectors.framework.spi.Configuration; +import org.identityconnectors.framework.spi.Connector; +import org.identityconnectors.framework.spi.ConnectorClass; +import org.identityconnectors.framework.spi.operations.*; +import org.identityconnectors.framework.common.exceptions.*; +import org.identityconnectors.framework.common.exceptions.ConfigurationException; +import org.identityconnectors.framework.common.exceptions.ConnectorException; +import org.identityconnectors.framework.common.objects.*; +import org.identityconnectors.common.logging.Log; +import org.identityconnectors.common.security.GuardedString; +import org.identityconnectors.framework.common.objects.filter.FilterTranslator; +//import edu.unc.polygon.connector.wordpress.WordpressRestConfiguration; + +import java.io.IOException; +import java.util.Iterator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.ArrayList; +import java.io.*; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.Object; + + +import com.evolveum.polygon.rest.AbstractRestConnector; + +/** + * @author ethan@unc.edu + * + */ +@ConnectorClass(displayNameKey = "connector.wordpress.rest.display", configurationClass = WordpressRestConfiguration.class) +public class WordpressRestConnector extends AbstractRestConnector implements TestOp, SchemaOp, DeleteOp, Connector, CreateOp, UpdateOp, SearchOp { + + private static final Log LOG = Log.getLog(WordpressRestConnector.class); + protected static final String ATTR_NAME = "username"; //icfs:name + private static final String ATTR_PASS = "password"; // OperationalAttributes.PASSWORD + private static final String ATTR_STATUS = "status"; // OperationalAttributes.ENABLE + private static final String ATTR_ID = "id"; + public static final String ATTR_MAIL = "email"; + public static final String ATTR_ROLES = "roles"; + public static final String ATTR_FIRST_NAME = "first_name"; + public static final String ATTR_LAST_NAME = "last_name"; + public static final String ATTR_FULL_NAME = "name"; + public static final String CONTENT_TYPE = "application/json"; + + + private WordpressRestConfiguration configuration; + + /*@Override + public Configuration getConfiguration() { + return configuration; + }*/ + + + @Override + public void init(Configuration configuration) { + LOG.info(">>> Initializing connector"); + + if (!(configuration instanceof WordpressRestConfiguration)) { + throw new ConfigurationException("Configuration is not instance of " + WordpressRestConfiguration.class.getName()); + } + + WordpressRestConfiguration wordpressConfig = (WordpressRestConfiguration) configuration; + wordpressConfig.validate(); + this.configuration = wordpressConfig; + //super.init(configuration); + getConfiguration(); + LOG.info(">>> Connector initialization finished"); + } + @Override + public void dispose() { + configuration = null; + //handler = null; + } + + + @Override + public void test() { + + LOG.ok("test - getting auth token"); + HttpEntityEnclosingRequestBase testRequest; + testRequest = new HttpPost(configuration.getWordpressRestUrl() + "/wp/v2/users"); + testRequest.setHeader("Content-Type", CONTENT_TYPE); + authHeader(testRequest); + + } + + @Override + public Schema schema() { + SchemaBuilder schemaBuilder = new SchemaBuilder(WordpressRestConnector.class); + //ObjectClassInfoBuilder ocBuilder = new ObjectClassInfoBuilder(); + //schemaBuilder.defineObjectClass(ocBuilder.build()); + Set attributes= new HashSet(); + AttributeInfoBuilder roles = new AttributeInfoBuilder(); + roles.setName("roles"); + roles.setCreateable(true); + roles.setUpdateable(true); + roles.setReadable(true); + roles.setRequired(false); + roles.setMultiValued(true); + attributes.add(roles.build()); + AttributeInfoBuilder name = new AttributeInfoBuilder(); + name.setName("name"); + name.setCreateable(true); + name.setUpdateable(true); + name.setReadable(true); + name.setRequired(false); + name.setMultiValued(false); + attributes.add(name.build()); + AttributeInfoBuilder last_name = new AttributeInfoBuilder(); + last_name.setName("last_name"); + last_name.setCreateable(true); + last_name.setUpdateable(true); + last_name.setReadable(true); + last_name.setRequired(false); + last_name.setMultiValued(false); + attributes.add(last_name.build()); + AttributeInfoBuilder first_name = new AttributeInfoBuilder(); + first_name.setName("first_name"); + first_name.setCreateable(true); + first_name.setUpdateable(true); + first_name.setReadable(true); + first_name.setRequired(false); + first_name.setMultiValued(false); + attributes.add(first_name.build()); + AttributeInfoBuilder username = new AttributeInfoBuilder(); + username.setName("username"); + username.setCreateable(true); + username.setUpdateable(true); + username.setReadable(true); + username.setRequired(false); + username.setMultiValued(false); + attributes.add(username.build()); + AttributeInfoBuilder id = new AttributeInfoBuilder(); + id.setName("id"); + id.setCreateable(true); + id.setUpdateable(true); + id.setReadable(true); + id.setRequired(false); + id.setMultiValued(false); + attributes.add(id.build()); + AttributeInfoBuilder email = new AttributeInfoBuilder(); + email.setName("email"); + email.setCreateable(true); + email.setUpdateable(true); + email.setReadable(true); + email.setRequired(false); + email.setMultiValued(false); + attributes.add(email.build()); + AttributeInfoBuilder password = new AttributeInfoBuilder(); + password.setName("password"); + password.setCreateable(true); + password.setUpdateable(true); + password.setReadable(true); + password.setRequired(false); + password.setMultiValued(false); + attributes.add(password.build()); + schemaBuilder.defineObjectClass(ObjectClass.ACCOUNT.getDisplayNameKey(),attributes); + LOG.info(">>> schema finished"); + return schemaBuilder.build(); + } + + public FilterTranslator createFilterTranslator(ObjectClass oc, OperationOptions oo) { + LOG.info("inside createFilterTranslator"); + return new WordpressFilterTranslator(); + } + + + @Override + public void executeQuery(ObjectClass oc, WordpressFilter filter, ResultsHandler handler, OperationOptions oo) { + //Integer searchId = (Integer) uid; + LOG.info(">>> executeQuery "); + if ( oc.is(ObjectClass.ACCOUNT_NAME)) { + JSONObject uidSearchResponseJson = new JSONObject(); + JSONObject jsonObject = new JSONObject(); + HttpEntityEnclosingRequestBase request; + if (filter != null && filter.byUid != null) { + Integer searchId = new Integer(filter.byUid); + request = new HttpGetWithBody(configuration.getWordpressRestUrl() + "/wp/v2/users/" + searchId); + } + else { + LOG.error("No attribute for search passed for an ObjectClass.ACCOUNT_NAME query"); + //this really shouldn't be possible + Integer searchId = new Integer(filter.byUid); + request = new HttpGetWithBody(configuration.getWordpressRestUrl() + "/wp/v2/users/" + searchId); + } + try { + uidSearchResponseJson = callRequest(request, jsonObject); + FileWriter file8 = new FileWriter("/tmp/file8.txt"); + file8.write(uidSearchResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + uidSearchResponseJson); + file8.flush(); + file8.close(); + ConnectorObjectBuilder builder = new ConnectorObjectBuilder(); + builder.setUid(new Uid(String.valueOf(uidSearchResponseJson.getInt(ATTR_ID)))); + String [] potentialAttributes = { ATTR_NAME, ATTR_MAIL, ATTR_FIRST_NAME, ATTR_LAST_NAME, ATTR_FULL_NAME}; + for ( String potentialAttribute: potentialAttributes ) { + LOG.info(">>> checking for attribute " + potentialAttribute ); + if ( uidSearchResponseJson.has(potentialAttribute) && uidSearchResponseJson.get(potentialAttribute) != null && !JSONObject.NULL.equals(uidSearchResponseJson.get(potentialAttribute)) ) { + LOG.info(">>> found attribute " + potentialAttribute ); + if ( potentialAttribute.equals(ATTR_NAME) ) { + builder.setName(uidSearchResponseJson.getString(potentialAttribute)); + } + else { + addAttr(builder, potentialAttribute, uidSearchResponseJson.getString(potentialAttribute)); + } + } + } + ConnectorObject connectorObject = builder.build(); + handler.handle(connectorObject); + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + } + else { + JSONArray searchResponseJson = new JSONArray(); + JSONObject jsonObject = new JSONObject(); + try { + HttpEntityEnclosingRequestBase request; + request = new HttpGetWithBody(configuration.getWordpressRestUrl() + "/wp/v2/users"); + searchResponseJson = callRequestArray(request, jsonObject); + FileWriter file9 = new FileWriter("/tmp/file9.txt"); + file9.write(searchResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + searchResponseJson); + file9.flush(); + file9.close(); + for ( int i = 0; i < searchResponseJson.length(); i++ ) { + JSONObject uidSearchResponseJson = searchResponseJson.getJSONObject(i); + LOG.info(">>> processing ID " + i); + ConnectorObjectBuilder builder = new ConnectorObjectBuilder(); + builder.setUid(new Uid(String.valueOf(uidSearchResponseJson.getInt(ATTR_ID)))); + String [] potentialAttributes = { ATTR_NAME, ATTR_MAIL, ATTR_FIRST_NAME, ATTR_LAST_NAME, ATTR_FULL_NAME}; + for ( String potentialAttribute: potentialAttributes ) { + LOG.info(">>> checking for attribute " + potentialAttribute ); + if ( uidSearchResponseJson.has(potentialAttribute) && uidSearchResponseJson.get(potentialAttribute) != null && !JSONObject.NULL.equals(uidSearchResponseJson.get(potentialAttribute)) ) { + LOG.info(">>> found attribute " + potentialAttribute ); + if ( potentialAttribute.equals(ATTR_NAME) ) { + builder.setName(uidSearchResponseJson.getString(potentialAttribute)); + } + else { + addAttr(builder, potentialAttribute, uidSearchResponseJson.getString(potentialAttribute)); + } + } + } + ConnectorObject connectorObject = builder.build(); + handler.handle(connectorObject); + } + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + } + } + + @NotThreadSafe + class HttpGetWithBody extends HttpEntityEnclosingRequestBase { + public static final String METHOD_NAME = "GET"; + public String getMethod() { return METHOD_NAME; } + + public HttpGetWithBody(final String uri) { + super(); + setURI(URI.create(uri)); + } + public HttpGetWithBody(final URI uri) { + super(); + setURI(uri); + } + public HttpGetWithBody() { super(); } + } + + @NotThreadSafe + class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase { + public static final String METHOD_NAME = "DELETE"; + public String getMethod() { return METHOD_NAME; } + + public HttpDeleteWithBody(final String uri) { + super(); + setURI(URI.create(uri)); + } + public HttpDeleteWithBody(final URI uri) { + super(); + setURI(uri); + } + public HttpDeleteWithBody() { super(); } + } + + @Override + public void delete(ObjectClass oc, Uid uid, OperationOptions oo) { + LOG.info(">>> delete {0} {1} {2}", oc, uid, oo); + if ( configuration.getWordpressSoftUserDelete() ) { + JSONObject deleteResponseJson = new JSONObject(); + JSONObject jsonObject = new JSONObject(); + JSONArray rolesJsonArray = new JSONArray(); + jsonObject.put(ATTR_ROLES, (Object) rolesJsonArray); + try { + LOG.info(">>> soft delete disable {0} {1} {2}", oc, uid, oo); + HttpEntityEnclosingRequestBase request; + request = new HttpPost(configuration.getWordpressRestUrl() + "/wp/v2/users/" + uid.getUidValue()); + deleteResponseJson = callRequest(request, jsonObject); + FileWriter file6 = new FileWriter("/tmp/file6.txt"); + file6.write(deleteResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + deleteResponseJson); + file6.flush(); + file6.close(); + + //String newUid = String.valueOf(createResponseJson.getInt("id")); + //return new Uid(newUid); + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + } + else { + LOG.info(">>> hard delete {0} {1} {2}", oc, uid, oo); + Integer recyclebinUser; + if ( configuration.getWordpressRecyclebinUser() == null ) { + recyclebinUser = 1; + } + else { + recyclebinUser = configuration.getWordpressRecyclebinUser(); + } + JSONObject deleteResponseJson = new JSONObject(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id",uid.getUidValue()); + jsonObject.put("force","true"); + jsonObject.put("reassign",recyclebinUser); + try { + //HttpDeleteWithBody request; + HttpDeleteWithBody request = new HttpDeleteWithBody(configuration.getWordpressRestUrl() + "/wp/v2/users/" + uid.getUidValue()); + deleteResponseJson = callRequest(request, jsonObject); + FileWriter file7 = new FileWriter("/tmp/file7.txt"); + file7.write(deleteResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + deleteResponseJson); + file7.flush(); + file7.close(); + + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + } + + //getHandler(oc).delete(oc, uid, oo); + + LOG.info(">>> delete finished"); + } + + @Override + public Uid create(ObjectClass objectClass, Set attributes, OperationOptions operationOptions) { + + Uid uid = null; + LOG.info("createOp, Uid: {0}, attributes: {1}", uid, attributes); + if (attributes == null || attributes.isEmpty()) { + LOG.info("request ignored, empty attributes"); + return uid; + } + + JSONObject jsonObject = new JSONObject(); + String mail = getStringAttr(attributes, ATTR_MAIL); + if (StringUtil.isBlank(mail)) { + throw new InvalidAttributeValueException("Missing mandatory attribute " + ATTR_MAIL); + } + if (mail != null) { + jsonObject.put(ATTR_MAIL, mail); + } + + String name = getStringAttr(attributes, Name.NAME); + if (StringUtil.isBlank(name)) { + throw new InvalidAttributeValueException("Missing mandatory attribute " + Name.NAME); + } + if (name != null) { + jsonObject.put(ATTR_NAME, name); + } + String full_name = getStringAttr(attributes, ATTR_FULL_NAME); + if (full_name != null) { + jsonObject.put(ATTR_FULL_NAME, full_name); + } + String first_name = getStringAttr(attributes, ATTR_FIRST_NAME); + if (first_name != null) { + jsonObject.put(ATTR_FIRST_NAME, first_name); + } + String last_name = getStringAttr(attributes, ATTR_LAST_NAME); + if (last_name != null) { + jsonObject.put(ATTR_LAST_NAME, last_name); + } + String[] roles = getMultiValAttr(attributes, ATTR_ROLES, null); + if ( roles != null ) { + JSONArray rolesJsonArray = new JSONArray(); + for ( int i = 0; i < roles.length; i++) { + String role = roles[i]; + JSONObject roleJsonObject = new JSONObject(role); + //roleJsonObject.put(role); + rolesJsonArray.put(i, (Object) roleJsonObject); + } + jsonObject.put(ATTR_ROLES, (Object) rolesJsonArray); + } + + final List passwordList = new ArrayList(1); + GuardedString guardedPassword = getAttr(attributes, OperationalAttributeInfos.PASSWORD.getName(), GuardedString.class); + if (guardedPassword != null) { + guardedPassword.access(new GuardedString.Accessor() { + @Override + public void access(char[] chars) { + passwordList.add(new String(chars)); + } + }); + } + String password = null; + if (!passwordList.isEmpty()) { + password = passwordList.get(0); + } + if (password != null) { + jsonObject.put(ATTR_PASS, password); + } + String jsonObjectString = jsonObject.toString(); + try { FileWriter file3 = new FileWriter("/tmp/file3.txt"); + file3.write(jsonObjectString); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + jsonObjectString); + file3.flush(); + file3.close(); + } catch (Exception e) { + System.out.println("exception writing file"); + } + JSONObject createResponseJson = new JSONObject(); + try { + HttpEntityEnclosingRequestBase request; + request = new HttpPost(configuration.getWordpressRestUrl() + "/wp/v2/users"); + createResponseJson = callRequest(request, jsonObject); + FileWriter file = new FileWriter("/tmp/file1.txt"); + file.write(createResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + createResponseJson); + file.flush(); + file.close(); + + String newUid = String.valueOf(createResponseJson.getInt("id")); + LOG.info("response ID: ", newUid); + return new Uid(newUid); + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + } + + @Override + public Uid update(ObjectClass objectClass, Uid uid, Set attributes, OperationOptions operationOptions) { + LOG.info("UpdateOp, Uid: {0}, attributes: {1}", uid, attributes); + if (attributes == null || attributes.isEmpty()) { + LOG.info("request ignored, empty attributes"); + return uid; + } + + JSONObject jsonObject = new JSONObject(); + String mail = getStringAttr(attributes, ATTR_MAIL); + /*if (StringUtil.isBlank(mail)) { + throw new InvalidAttributeValueException("Missing mandatory attribute " + ATTR_MAIL); + }*/ + if (mail != null) { + jsonObject.put(ATTR_MAIL, mail); + } + + String name = getStringAttr(attributes, Name.NAME); + /* + if (StringUtil.isBlank(name)) { + throw new InvalidAttributeValueException("Missing mandatory attribute " + Name.NAME); + }*/ + if (name != null) { + jsonObject.put(ATTR_NAME, name); + } + String full_name = getStringAttr(attributes, ATTR_FULL_NAME); + if (full_name != null) { + jsonObject.put(ATTR_FULL_NAME, full_name); + } + String first_name = getStringAttr(attributes, ATTR_FIRST_NAME); + if (first_name != null) { + jsonObject.put(ATTR_FIRST_NAME, first_name); + } + String last_name = getStringAttr(attributes, ATTR_LAST_NAME); + if (last_name != null) { + jsonObject.put(ATTR_LAST_NAME, last_name); + } + String[] roles = getMultiValAttr(attributes, ATTR_ROLES, null); + if ( roles != null ) { + JSONArray rolesJsonArray = new JSONArray(); + for ( int i = 0; i < roles.length; i++) { + String role = roles[i]; + JSONObject roleJsonObject = new JSONObject(role); + //roleJsonObject.put(role); + rolesJsonArray.put(i, (Object) roleJsonObject); + } + jsonObject.put(ATTR_ROLES, (Object) rolesJsonArray); + } + + final List passwordList = new ArrayList(1); + GuardedString guardedPassword = getAttr(attributes, OperationalAttributeInfos.PASSWORD.getName(), GuardedString.class); + if (guardedPassword != null) { + guardedPassword.access(new GuardedString.Accessor() { + @Override + public void access(char[] chars) { + passwordList.add(new String(chars)); + } + }); + } + String password = null; + if (!passwordList.isEmpty()) { + password = passwordList.get(0); + } + if (password != null) { + jsonObject.put(ATTR_PASS, password); + } + String jsonObjectString = jsonObject.toString(); + try { FileWriter file4 = new FileWriter("/tmp/file4.txt"); + file4.write(jsonObjectString); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + jsonObjectString); + file4.flush(); + file4.close(); + } catch (Exception e) { + System.out.println("exception writing file"); + } + JSONObject createResponseJson = new JSONObject(); + try { + HttpEntityEnclosingRequestBase request; + request = new HttpPost(configuration.getWordpressRestUrl() + "/wp/v2/users/" + uid.getUidValue()); + createResponseJson = callRequest(request, jsonObject); + FileWriter file5 = new FileWriter("/tmp/file5.txt"); + file5.write(createResponseJson.toString()); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + createResponseJson); + file5.flush(); + file5.close(); + + String newUid = String.valueOf(createResponseJson.getInt("id")); + return new Uid(newUid); + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + + } + protected JSONObject callRequest(HttpEntityEnclosingRequestBase request, JSONObject jo) throws IOException { + // don't log request here - password field !!! + LOG.info("request URI: {0}", request.getURI()); + request.setHeader("Content-Type", CONTENT_TYPE); + CloseableHttpClient client = HttpClients.createDefault(); + authHeader(request); + HttpEntity entity = new ByteArrayEntity(jo.toString().getBytes("UTF-8")); + request.setEntity(entity); + CloseableHttpResponse response = client.execute(request); + LOG.info("response: "); + String responseText = EntityUtils.toString(response.getEntity()); + FileWriter file = new FileWriter("/tmp/file2.txt"); + file.write(responseText); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + responseText); + file.flush(); + file.close(); + processResponseErrors(response); + JSONObject result = new JSONObject (responseText); + LOG.info("response body: "); + closeResponse(response); + return result; + } + + protected JSONArray callRequestArray(HttpEntityEnclosingRequestBase request, JSONObject jo) throws IOException { + // don't log request here - password field !!! + LOG.info("request URI: {0}", request.getURI()); + request.setHeader("Content-Type", CONTENT_TYPE); + CloseableHttpClient client = HttpClients.createDefault(); + authHeader(request); + HttpEntity entity = new ByteArrayEntity(jo.toString().getBytes("UTF-8")); + request.setEntity(entity); + CloseableHttpResponse response = client.execute(request); + LOG.info("response: "); + String responseText = EntityUtils.toString(response.getEntity()); + FileWriter file = new FileWriter("/tmp/file2.txt"); + file.write(responseText); + System.out.println("Successfully Copied JSON Object to File..."); + System.out.println("\nJSON Object: " + responseText); + file.flush(); + file.close(); + processResponseErrors(response); + JSONArray result = new JSONArray (responseText); + LOG.info("response body: "); + closeResponse(response); + return result; + } + + + private void authHeader(HttpRequest request) { + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("username", configuration.getWordpressUsername()); + jsonObject.put("password", configuration.getWordpressPassword()); + JSONObject jwtTokenResponse = new JSONObject(); + LOG.info("Retrieving Bearer token"); + try { + CloseableHttpClient client = HttpClients.createDefault(); + HttpEntityEnclosingRequestBase tokenRequest; + LOG.info(configuration.getWordpressRestUrl()); + LOG.info(configuration.getWordpressRestUrl() + "/jwt-auth/v1/token"); + tokenRequest = new HttpPost(configuration.getWordpressRestUrl() + "/jwt-auth/v1/token"); + tokenRequest.setHeader("Content-Type", CONTENT_TYPE); + HttpEntity jwtEntity = new ByteArrayEntity(jsonObject.toString().getBytes("UTF-8")); + tokenRequest.setEntity(jwtEntity); + CloseableHttpResponse jwtResponse = client.execute(tokenRequest); + LOG.info("response: " ); + processResponseErrors(jwtResponse); + jwtTokenResponse = new JSONObject (EntityUtils.toString(jwtResponse.getEntity())); + //jwtTokenResponse = callRequest(tokenRequest, jsonObject); + } catch (IOException IOE) { + throw new ConnectorIOException(IOE.getMessage(), IOE); + } + String token = jwtTokenResponse.getString("token"); + LOG.info("Retrieved token for user", jwtTokenResponse.getString("user_display_name")); + request.setHeader("Authorization", "Bearer " + token); + + } + + /* private void closeResponse(CloseableHttpResponse response) { + + super.closeResponse(); + } */ + +}