Compare commits

...

195 Commits

Author SHA1 Message Date
Ahmed Salah Tawfik Ibrahim 364b076af2 SNL new version 2024-04-16 15:20:37 +02:00
Ahmed Salah Tawfik Ibrahim bd932d3fc6 fix dependency 2024-04-15 15:09:07 +02:00
Ahmed Salah Tawfik Ibrahim ae4f4e593c bug fix 2024-04-12 16:52:08 +02:00
Ahmed Salah Tawfik Ibrahim ccb52f1770 bug fix 2024-04-12 16:39:56 +02:00
Ahmed Salah Tawfik Ibrahim 24fba77a4f bug fix 2024-04-12 16:34:24 +02:00
Ahmed Salah Tawfik Ibrahim 0419a89420 debugging logs added 2024-04-12 16:00:56 +02:00
Ahmed Salah Tawfik Ibrahim f65486e9c0 trigger build 2024-04-11 12:47:26 +02:00
Ahmed Salah Tawfik Ibrahim f46bbbc0c0 Fixed Version 2024-01-29 17:46:55 +01:00
Ahmed Salah Tawfik Ibrahim 1dad8e8eb8 fixed notification method 2024-01-29 15:46:21 +01:00
Ahmed Salah Tawfik Ibrahim 1254246b0d small test 2024-01-15 14:39:24 +01:00
Ahmed Salah Tawfik Ibrahim c5e0bb84e8 Method fix 2023-12-13 14:07:11 +01:00
Ahmed Salah Tawfik Ibrahim 16228bb5b0 Ignore Lib Path 2023-12-07 12:08:01 +01:00
Massimiliano Assante 6242694d8d trying fix for search posts missing deps 2023-12-07 09:31:50 +01:00
Massimiliano Assante bfc98ba8c0 ready to release 2023-12-06 19:03:26 +01:00
Massimiliano Assante 5ddd78cbdd Feature 25766, new impl for get users by role in a VRE 2023-12-06 18:57:33 +01:00
Massimiliano Assante 9067e8ad7e alpha 2023-12-06 18:45:29 +01:00
Massimiliano Assante bc4892af73 made it more robust 2023-12-06 18:38:33 +01:00
Massimiliano Assante 0232f2c9b8 test 2023-12-06 17:48:06 +01:00
Massimiliano Assante 239d7a69c0 test 2023-12-06 17:28:44 +01:00
Massimiliano Assante 5dd5497cf0 test get Roles new 2023-12-06 17:28:03 +01:00
Ahmed Salah Tawfik Ibrahim a7bd85ec57 Working Service 2023-12-06 12:18:22 +01:00
Ahmed Salah Tawfik Ibrahim f6e40e2bbf Working Service 2023-12-05 17:05:38 +01:00
Ahmed Salah Tawfik Ibrahim f5633760d9 Working Service 2023-12-05 17:01:17 +01:00
Ahmed Salah Tawfik Ibrahim bfa2fa36aa Working Service 2023-12-05 16:42:51 +01:00
Ahmed Salah Tawfik Ibrahim 675f509712 Working Service 2023-12-05 16:40:59 +01:00
Ahmed Salah Tawfik Ibrahim 89649a0308 Working Service 2023-12-05 16:32:04 +01:00
Massimiliano Assante 851df04a13 ready to release 2023-12-04 18:42:40 +01:00
Massimiliano Assante d77def7a98 Add REST resources for all the functions in social networking library 2023-12-04 18:39:10 +01:00
Ahmed Salah Tawfik Ibrahim 85a9f1d82c Working Service 2023-12-04 18:28:53 +01:00
Ahmed Salah Tawfik Ibrahim 9ac252085b Working Service 2023-12-04 18:28:07 +01:00
Ahmed Salah Tawfik Ibrahim ef568759ea Working Service 2023-12-04 18:24:55 +01:00
Ahmed Salah Tawfik Ibrahim 1861f0a4d6 Working Service 2023-12-04 17:34:47 +01:00
Ahmed Salah Tawfik Ibrahim d20bb95b1a New Endpoint - attachment path 2023-11-28 19:39:34 +01:00
Ahmed Salah Tawfik Ibrahim fe5e4c7884 New Endpoint 2023-11-28 11:27:20 +01:00
Ahmed Salah Tawfik Ibrahim 26cefd0ac0 Added Author 2023-11-24 11:53:20 +01:00
Ahmed Salah Tawfik Ibrahim a55ba31d9a Social service - More REST API resoruces 2023-11-22 19:52:25 +01:00
Ahmed Salah Tawfik Ibrahim 0551ee95f3 Social service - More REST API resoruces 2023-11-21 18:38:57 +01:00
Ahmed Salah Tawfik Ibrahim ef25c80d68 Social service - cassandra 4 - New POM 2023-11-14 11:32:37 +01:00
Ahmed Salah Tawfik Ibrahim cd1e77e4fc Social service - cassandra 4 2023-11-13 11:33:37 +01:00
Massimiliano Assante 6fce7cf11f ready to release 2023-09-29 18:17:56 +02:00
Massimiliano Assante 23e6026ef4 removed memcached 2023-09-29 18:07:47 +02:00
Massimiliano Assante 522e04d50e removed memcached 2023-09-29 18:07:24 +02:00
Massimiliano Assante 0c4c8d61d1 minor fix 2023-09-29 17:52:51 +02:00
Massimiliano Assante cf100591eb minor fix 2023-09-29 17:44:32 +02:00
Massimiliano Assante 2cd6c13712 updated pom version 2023-09-29 15:12:33 +02:00
Massimiliano Assante 599ac563b8 bug fix #25760 2023-09-29 11:34:01 +02:00
Massimiliano Assante b86d5501fe bugfix 25760 2023-09-29 11:32:16 +02:00
Massimiliano Assante 2e6d0c7521 ready to release 2023-02-09 17:38:26 +01:00
Massimiliano Assante c5382532e5 for CD 2023-02-09 17:16:09 +01:00
Massimiliano Assante 5adae80a1a added the comment in the result object 2023-02-09 17:08:54 +01:00
Massimiliano Assante 628e74258e ready to release 2023-02-09 15:48:51 +01:00
Massimiliano Assante 80aed8b486 renamed postid for coherence 2023-02-09 15:40:56 +01:00
Massimiliano Assante 8b58a29d9f fixed unlike method 2023-02-09 15:31:11 +01:00
Massimiliano Assante 2ebd2b7f8f fixed postid param 2023-02-09 15:09:38 +01:00
Massimiliano Assante 735bb8149b merged conflicts 2023-02-09 12:55:34 +01:00
Massimiliano Assante 77b1c20854 Merge remote-tracking branch 'origin/Feature/24456' 2023-02-09 12:53:16 +01:00
Massimiliano Assante 7bb985500c like and unlike added, to be tested 2023-02-09 12:47:01 +01:00
Massimiliano Assante ef4d5b22ca fix 2023-02-08 16:29:00 +01:00
Massimiliano Assante 09ca845311 found the bug 2023-02-08 16:21:17 +01:00
Massimiliano Assante 5af56a039a trying fix 2023-02-08 16:08:16 +01:00
Massimiliano Assante f67c38ef2d revised writeComment method 2023-02-08 15:37:24 +01:00
Massimiliano Assante cb583b0a50 added comment method with notification, still need testing 2023-02-08 14:29:57 +01:00
Massimiliano Assante 9f696b7f54 commit comment 2023-02-07 11:42:49 +01:00
Massimiliano Assante 4fb2cebe8d fixed the comment object that was wrong 2023-02-02 20:35:48 +01:00
Massimiliano Assante 60e025cb5a fixed bug 2023-02-02 20:23:51 +01:00
Massimiliano Assante 6066406a08 fixed bug 2023-02-02 20:18:14 +01:00
Massimiliano Assante bffac60eb1 added the comment post method 2023-02-02 20:11:52 +01:00
Massimiliano Assante cdf61e73c4 added get-post by id 2023-02-02 19:17:37 +01:00
Massimiliano Assante db5834fcef testing CD 2022-12-20 10:23:56 +01:00
Massimiliano Assante b28f24e4b4 fixed Support #24314 2022-12-15 18:57:36 +01:00
Massimiliano Assante 2b7eb284c5 ready to release 2022-10-25 18:46:43 +02:00
Massimiliano Assante 7bd02b6b01 added likes interface 2022-10-25 18:38:20 +02:00
Massimiliano Assante b068f92888 added getAllCommentsByPostId
fixed javadoc
2022-10-25 18:12:29 +02:00
Massimiliano Assante e2c4be4633 fixed typo 2022-10-25 17:04:14 +02:00
Massimiliano Assante 61203ff9f7 Feature #24022 Add api the get posts with range filter parameters 2022-10-25 16:50:26 +02:00
Massimiliano Assante f0fa56a7dd added check for TokenUtils 2022-10-24 16:32:41 +02:00
Massimiliano Assante 95edfad9db commented version shub2 for release 2022-10-20 19:23:58 +02:00
Massimiliano Assante 15dcd38edb added support for set Message read / unread 2022-10-20 19:21:42 +02:00
Massimiliano Assante 991ad5ca90 ready to release 2022-10-20 19:18:55 +02:00
Massimiliano Assante dcaaa4836b ready to release 2022-10-20 19:17:13 +02:00
Massimiliano Assante 3b367774cc support attachments for write message 2022-10-20 14:45:17 +02:00
Massimiliano Assante 1455a59ac8 updated changelog 2022-10-20 12:22:50 +02:00
Massimiliano Assante 26b8336f05 fixed token utils to support both IAM and Legacy auth corner cases 2022-10-19 19:59:25 +02:00
Massimiliano Assante c6a625d800 fixed typo 2022-10-19 17:23:40 +02:00
Massimiliano Assante 3f78a78926 allow IAM to send Workspace notifications 2022-10-19 17:20:52 +02:00
Massimiliano Assante ff33c24f7c fixed also for messages 2022-10-19 17:19:20 +02:00
Massimiliano Assante a4b8e945d6 o 2022-10-19 17:12:56 +02:00
Massimiliano Assante 93d7af4473 o 2022-10-19 17:11:15 +02:00
Massimiliano Assante 1003c32ffc added log 2022-10-19 16:28:03 +02:00
Massimiliano Assante 72bb6c65ba added possibility to send notifications from Catalogue 2022-10-19 15:54:45 +02:00
Massimiliano Assante 8a60b754ee updated some deps 2022-09-20 18:26:16 +02:00
Massimiliano Assante f466044eee added maven.compiler.source 1.8 2022-09-20 18:25:15 +02:00
Massimiliano Assante 5f68ed34cc - Feature #23891 Refactored following updates social lib 2022-09-20 18:20:03 +02:00
Massimiliano Assante c726b73f1f fix on method get user post quantity 2022-09-20 18:09:51 +02:00
Massimiliano Assante 8470bb032b fixed pom for source version 2022-09-20 16:57:23 +02:00
Massimiliano Assante c9f542fb8f adapted to be built widh JDK 11 2022-09-20 16:53:48 +02:00
Massimiliano Assante 1ed2f32c49 ready to release 2022-09-16 14:35:51 +02:00
Massimiliano Assante 7879cb795f added logs at INFO advising Notificatiom are disabled for the user 2022-09-16 14:33:54 +02:00
Massimiliano Assante 18b2fd231d aaaa 2022-09-16 12:47:30 +02:00
Massimiliano Assante 4efb919c00 aaaa 2022-09-16 12:41:26 +02:00
Massimiliano Assante 4b80189a6e ssss 2022-09-16 12:39:57 +02:00
Massimiliano Assante 9a4784a250 aaa 2022-09-16 12:34:10 +02:00
Massimiliano Assante 87c06555ca aaaa 2022-09-16 12:33:04 +02:00
Massimiliano Assante 944d14aaa0 aaa 2022-09-16 12:26:26 +02:00
Massimiliano Assante 4b50b72ff5 changed params for set notifications 2022-09-16 12:14:11 +02:00
Massimiliano Assante 195d8f1f65 minor fix 2022-09-16 11:46:41 +02:00
Massimiliano Assante cfcbec3bf8 fixed auth on methods 2022-09-16 10:12:22 +02:00
Massimiliano Assante b7169b101c added query params 2022-09-16 08:56:55 +02:00
Massimiliano Assante 7a6f95d466 mising query param 2022-09-15 14:33:13 +02:00
Massimiliano Assante 3ee604924c implemented set and get 2022-09-15 14:24:04 +02:00
Massimiliano Assante 440dd5236b typo in pom fixed 2022-09-14 16:37:26 +02:00
Massimiliano Assante 2c2a68b580 partial implementation (reads) 2022-09-14 16:26:17 +02:00
Massimiliano Assante ea37bcb93c minor fix to DocsGenertor class 2022-09-13 14:24:25 +02:00
Massimiliano Assante e0a3e9f516 Sphinx documentation added 2022-09-12 15:36:38 +02:00
Massimiliano Assante f7cefc13af Sphinx documentation added 2022-09-12 15:35:49 +02:00
Massimiliano Assante 42deae87db docs ready 2022-09-12 15:27:07 +02:00
Massimiliano Assante b05208680b fixed typo 2022-09-05 10:49:18 +02:00
Massimiliano Assante 234c1df4b4 fixed docs 2022-09-05 10:29:53 +02:00
Massimiliano Assante dc7071168d added docs 2022-08-30 16:33:39 +02:00
Massimiliano Assante a19f1eecdd added documentation 2022-08-30 16:33:27 +02:00
Massimiliano Assante 39e402cb31 sphinx fix 2022-08-30 11:58:54 +02:00
Massimiliano Assante 447b168d60 fixed css template location 2022-08-30 11:48:52 +02:00
Massimiliano Assante 8966264180 sphinx docs 2022-08-30 11:36:33 +02:00
Massimiliano Assante 6b6b9b39e0 sphinx docs 2022-08-30 11:21:01 +02:00
Massimiliano Assante 1d02f99176 ready to release 2022-07-27 11:00:43 +02:00
Massimiliano Assante 280b1bde27 fixed methos isUserTokenDefault 2022-07-27 10:20:40 +02:00
Massimiliano Assante a4fdfcc547 fix for Incident #23668 weird accept headers 2022-07-26 12:39:17 +02:00
Massimiliano Assante ac9a5f39ee fixed swagger base url 2022-05-25 18:04:59 +02:00
Massimiliano Assante b115782a86 fixed changelog 2022-05-16 11:04:50 +02:00
Massimiliano Assante 8595de3daf fixed pom for release 2022-05-16 10:53:27 +02:00
Massimiliano Assante bc5ce9e00d Feature #23186, Full notifications support for social service 2022-05-16 10:51:41 +02:00
Massimiliano Assante af527e6e9d disabled java client 2022-05-09 16:41:30 +02:00
Massimiliano Assante c3b1c8ab53 fixed check 2022-05-09 12:34:25 +02:00
Massimiliano Assante e90bdcedb2 fix 2022-05-09 12:27:51 +02:00
Massimiliano Assante 5fd457f230 fixed 2022-05-09 12:19:42 +02:00
Massimiliano Assante c07d618220 check user 2022-05-09 11:45:09 +02:00
Massimiliano Assante 70ce721d6b check the user 2022-05-09 11:44:33 +02:00
Massimiliano Assante d632e3ed1a added support for catalogue notifications 2022-05-09 10:31:20 +02:00
Massimiliano Assante f7d2a1e569 added partial support for catalogue notifications 2022-05-06 17:15:24 +02:00
Massimiliano Assante 5111439f3e removed some deprecated methods 2022-05-06 10:47:26 +02:00
Massimiliano Assante 4982250c26 workspace notifications supported completed 2022-05-05 14:32:25 +02:00
Massimiliano Assante f718c527c0 updated aslsocial deps 2022-05-05 14:13:51 +02:00
Massimiliano Assante 3f9c5d406f many notification added 2022-05-05 13:38:47 +02:00
Massimiliano Assante 100d2484ff implemented groups notification 2022-05-05 11:04:31 +02:00
Massimiliano Assante 410f540219 refactored method notifications workspace 2022-05-05 10:23:02 +02:00
Massimiliano Assante cd0f65cf35 refactored 2022-05-04 18:16:22 +02:00
Massimiliano Assante 306ecf935b refactored 2022-05-04 16:32:48 +02:00
Massimiliano Assante b45fd2c323 fixed bug 2022-05-04 12:32:29 +02:00
Massimiliano Assante 764c9f997a updated pom 2022-05-04 11:38:54 +02:00
Massimiliano Assante 470cd59192 refactored workspace classes 2022-05-04 11:28:38 +02:00
Massimiliano Assante 92bb73c8f9 revised item new notification 2022-05-04 10:37:52 +02:00
Massimiliano Assante 92dfed500d boh 2022-05-04 08:59:59 +02:00
Massimiliano Assante 1e7a371ff6 updated pon 2022-05-03 17:07:46 +02:00
Massimiliano Assante 692e12d9dc fixed bug 2022-05-03 16:43:55 +02:00
Massimiliano Assante ebecec2c1e fixed bug 2022-05-03 15:56:56 +02:00
Massimiliano Assante 7810eba3db fixed bug 2022-05-03 15:43:18 +02:00
Massimiliano Assante bf44c985b7 added some debug logs 2022-05-03 11:02:17 +02:00
Massimiliano Assante b69fd1270e removed Workspace Notification Message class 2022-05-02 18:47:52 +02:00
Massimiliano Assante d923f21c2d first notification working 2022-04-29 14:57:15 +02:00
Massimiliano Assante 04493ed776 revised job notifications 2022-04-27 18:29:33 +02:00
Massimiliano Assante be9f36822f added folder unshare 2022-04-27 17:54:51 +02:00
Massimiliano Assante fd1eb389c3 partially implemented worspace notif support 2022-04-21 17:50:48 +02:00
Lucio Lelii d8a4046eed added NotificationMessage 2022-04-21 13:20:33 +02:00
Massimiliano Assante 0e7299f104 branch feature 23186 2022-04-21 12:17:55 +02:00
Massimiliano Assante b3c7121138 Merge branch 'EnunciateIntegration' 2022-04-11 15:15:39 +02:00
Massimiliano Assante ebcb4b2dfe updated pom 2022-04-11 15:15:06 +02:00
Massimiliano Assante 964f2023d8 updated swagger endpoint 2022-04-11 12:50:29 +02:00
Massimiliano Assante cb97a0988c updated swagger base path 2022-04-11 12:47:48 +02:00
Massimiliano Assante b58f65012c ready to release 2022-04-07 18:33:50 +02:00
Massimiliano Assante bd6f3bbbab Merge branch 'EnunciateIntegration'
Conflicts:
	.settings/org.eclipse.wst.common.component
2022-04-07 18:31:22 +02:00
Massimiliano Assante ac5a9ba510 movete 2022-04-07 18:30:20 +02:00
Massimiliano Assante 4f9dd17395 movete 2022-04-07 18:29:00 +02:00
Massimiliano Assante 0153e5d7c7 ss 2022-04-07 18:27:40 +02:00
Massimiliano Assante a9fcd4df5f enriched docs 2022-04-07 18:11:56 +02:00
Massimiliano Assante 1057a7fcad enunciate integrated and working 2022-04-07 16:25:26 +02:00
Massimiliano Assante 9956a9ecda ready to release 2021-06-21 15:21:28 +02:00
Lucio Lelii 743c4d4ea4 Update 'CHANGELOG.md' 2021-04-30 12:32:31 +02:00
lucio.lelii 1ca35916cd porting to storagehub for messages 2021-04-29 16:53:35 +02:00
Massimiliano Assante ad43c3782c restored version with HL Dependency for messaging 2021-04-19 12:23:09 +02:00
Massimiliano Assante 83ebb52e89 removed home library dependency 2021-04-14 16:33:16 +02:00
Massimiliano Assante 80117c2418 replaced previous version 2020-12-01 18:10:15 +01:00
Massimiliano Assante 2617335d6c try to build 2020-12-01 17:55:46 +01:00
Massimiliano Assante 3da56deb1e Updated BOM gcube-smartgears-bom 2020-10-08 09:28:31 +02:00
Fabio Sinibaldi 2537e64257 adoption of gcube-smartgears-bom.2.0.0-SNAPSHOT 2020-10-07 16:28:48 +02:00
Massimiliano Assante cbe9f3cf00 updated rev number for fix Bug #19210 2020-05-05 16:22:17 +02:00
Massimiliano Assante d62a42f399 Fix Bug #19210 Social Service Write message on RootVO in preprod 2020-05-05 16:16:03 +02:00
Massimiliano Assante bc87a841d7 removed snapshot from version 2020-04-06 12:42:05 +02:00
Massimiliano Assante 0655abdcdd reverted pom 2020-04-06 12:26:35 +02:00
Massimiliano Assante 4f330001e8 added httpclient e httpcore 2020-04-06 12:20:45 +02:00
Massimiliano Assante 4841f98ad0 added cassandra all 2020-04-06 12:08:43 +02:00
Massimiliano Assante 1472b0e0c2 added cassandra deps 2020-04-06 12:06:00 +02:00
Massimiliano Assante 55a48cccae added json-simple dep 2020-04-06 11:54:37 +02:00
Massimiliano Assante fac9dff9f4 added commons-logging 2020-04-06 11:44:17 +02:00
Massimiliano Assante e049419e5a added commonc codec dependency 2020-04-06 11:35:48 +02:00
Massimiliano Assante dbf750202a Feature #19019 add context name to rest method 2/people/profile 2020-04-06 11:29:22 +02:00
73 changed files with 5730 additions and 2537 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@ -20,12 +20,12 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target/

View File

@ -8,7 +8,9 @@ org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -1,13 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="social-networking-library-ws">
<wb-module deploy-name="social-networking-library-ws-3.0.0-SNAPSHOT">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<dependent-module archiveName="social-util-library-1.7.2.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/social-util-library/social-util-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="java-output-path" value="/social-networking-library-ws/target/classes"/>
<property name="context-root" value="social-networking-library-ws"/>
<property name="java-output-path" value="/social-networking-library-ws/target/classes"/>
</wb-module>
</project-modules>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="jst.jaxrs" version="1.1"/>
<installed facet="java" version="1.8"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="jst.jaxrs" version="2.1"/>
<installed facet="wst.jsdt.web" version="1.0"/>
</faceted-project>

107
CHANGELOG.md Normal file
View File

@ -0,0 +1,107 @@
# Changelog
## [v3.0.0-SNAPSHOT] - 2023-12-06
- Feature #26193, new impl for get users by role in a VRE
- Replace Astyanx Java client for Cassandra 2 with Datastax client for Cassandra 4
- Add REST resources for all the functions in social networking library
## [v2.9.1] - 2023-09-28
- Fix for Bug #25760 not closing connection to distributed cached
- Removed memcached dep
## [v2.9.0] - 2023-02-13
- Feature #24456 social-networking rest api endpoints (comments, Likes, GetPost)
## [v2.8.0] - 2022-10-20
- Feature #23891 Refactored following updates social lib
- Feature #23847 Social service: temporarily block of notifications for given username(s)
- Feature #23439 Please allow an IAM client to send notifications OPEN
- Feature #23991 Support attachments through notification / message API
- Feature #23995 added support for set Message read / unread
- Feature #24022 added get posts By PostId with range filter parameters and get Comments By PostId
## [v2.7.0] - 2022-09-12
- Sphinx documentation added
## [v2.6.2] - 2022-07-27
- Bug fix #23695 social service 2/people/profile api fails sometimes with error 500
- get-email method was not working with UMA tokens
## [v2.6.0] - 2022-05-16
- Feature #23186, Full notifications support for social service
## [v2.5.0] - 2022-04-06
- enunciate integration
## [v2.4.0] - 2021-04-30
- Feature #21179 porting to storagehub messages
## [v2.3.3] - 2020-10-08
- removed jackson dependency
## [v2.3.0] - 2019-10-02
- added support for mentions with @ in user's post as well as application posts
### Features
- Added the property cataloguePortletURL and the method [#19440]
## [v2.2.4] - 2019-07-22
### Features
- Bug fix #17269, SocialNetworking service passes wrong email sender in email notifications
## [v2.2.3] - 2019-04-05
### Features
- added get-oauth-profile method for returning Google similar JSON Profile
- added support for caches (ehcache)
### Fixes
- Fix for #10997
- Support for tickets #9333, #9332, #9276
## [v2.0.0] - 2017-02-01
### Features
- Moved as service on top of SmartGears
- Exploiting Liferay's Web APIs
## [v1.4.0] - 2016-12-01
### Features
- Custom jackson object mapper is used to have snake case fields'names
- Improved users version 2 resource with more methods
## [v1.3.0] - 2016-10-10
### Features
- Moved to new Authorization Framework
- Added method to send Messages
- Added new version for the APIs that accept/return JSON
- gCube Token is discovered before every call is executed by a filter
## [v1.0.0] - 2015-12-21
First release
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

26
FUNDING.md Normal file
View File

@ -0,0 +1,26 @@
# Acknowledgments
The projects leading to this software have received funding from a series of European Union programmes including:
- the Sixth Framework Programme for Research and Technological Development
- [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
- the Seventh Framework Programme for research, technological development and demonstration
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
- the H2020 research and innovation programme
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);

View File

@ -17,14 +17,17 @@
See [Releases](https://code-repo.d4science.org/gCubeSystem/social-networking-library-ws/releases).
## Authors
* **Costantino Perciante** - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
* **Massimiliano Assante** ([ORCID](https://orcid.org/0000-0002-3761-1492)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/People/M.Assante)
* **Costantino Perciante**
* **Ahmed Ibrahim** ([ORCID](https://orcid.org/0009-0001-3009-5755)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/en/about/people-detail/976/Ahmed_Salah_Tawfik_Ibrahim)
## Maintainers
* **Lucio Lelii** - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
* **Massimiliano Assante** - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
* **Massimiliano Assante** ([ORCID](https://orcid.org/0000-0002-3761-1492)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/People/M.Assante)
* **Ahmed Ibrahim** ([ORCID](https://orcid.org/0009-0001-3009-5755)) - [ISTI-CNR Infrascience Group](https://www.isti.cnr.it/en/about/people-detail/976/Ahmed_Salah_Tawfik_Ibrahim)
## License
@ -37,12 +40,4 @@ open-source software toolkit used for building and operating Hybrid Data
Infrastructures enabling the dynamic deployment of Virtual Research Environments
by favouring the realisation of reuse oriented policies.
The projects leading to this software have received funding from a series of European Union programmes including:
- the Sixth Framework Programme for Research and Technological Development
- DILIGENT (grant no. 004260);
- the Seventh Framework Programme for research, technological development and demonstration
- D4Science (grant no. 212488), D4Science-II (grant no.239019), ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine(grant no. 283644);
- the H2020 research and innovation programme
- BlueBRIDGE (grant no. 675680), EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant no. 654119), SoBigData (grant no. 654024),DESIRA (grant no. 818194), ARIADNEplus (grant no. 823914), RISIS2 (grant no. 824091), PerformFish (grant no. 727610), AGINFRAplus (grant no. 731001);
The projects leading to this software have received funding from a series of European Union programmes see [FUNDING.md](FUNDING.md)

View File

@ -1,73 +0,0 @@
<ReleaseNotes>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-3-0"
date="2019-10-02">
<Change>added support for mentions with @ in user's post as well as application posts</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-2-4"
date="2019-07-22">
<Change>bug fix #17269, SocialNetworking service passes wrong email sender in email notifications</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-2-3"
date="2019-04-05">
<Change>added get-oauth-profile method for returning Google similar
JSON Profile</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-1-1"
date="2018-01-20">
<Change>Fix for #10997</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-1-0"
date="2017-08-01">
<Change>Support for tickets #9333, #9332, #9276</Change>
<Change>Added support for caches (ehcache)</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-0-1"
date="2017-05-01">
<Change>Fixed bug #8685</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.2-0-0"
date="2017-02-01">
<Change>Moved as service on top of SmartGears</Change>
<Change>Exploiting Liferay's Web APIs</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.1-4-0"
date="2016-12-01">
<Change>Custom jackson object mapper is used to have snake case
fields'names
</Change>
<Change>Improved users version 2 resource with more methods</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.1-3-0"
date="2016-10-10">
<Change>Moved to new Authorization Framework</Change>
<Change>Added method to send Messages</Change>
<Change>Added new version for the APIs that accept/return JSON
</Change>
<Change>Token is discovered before every call is executed by a filter
</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.1-2-0"
date="2016-06-10">
<Change>Support for new portal (gCube 4.0.0)</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.1-1-0"
date="2016-04-10">
<Change>Minor bug fixes (look at support ticket #2971)</Change>
</Changeset>
<Changeset
component="org.gcube.portal.social-networking-library-ws.1-0-0"
date="2015-12-21">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

View File

@ -1,31 +0,0 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>servicearchive</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>/</baseDirectory>
<fileSets>
<fileSet>
<directory>${distroDirectory}</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>README</include>
<include>LICENSE</include>
<include>changelog.xml</include>
<include>profile.xml</include>
</includes>
<fileMode>755</fileMode>
<filtered>true</filtered>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${build.finalName}.${project.packaging}</source>
<outputDirectory>/${artifactId}</outputDirectory>
</file>
</files>
</assembly>

View File

@ -1 +0,0 @@
${gcube.license}

View File

@ -1,62 +0,0 @@
The gCube System - ${name}
--------------------------------------------------
${description}
${gcube.description}
${gcube.funding}
Version
--------------------------------------------------
${version} (${buildDate})
Please see the file named "changelog.xml" in this directory for the release notes.
Authors
--------------------------------------------------
* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Maintainers
-----------
* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
Binaries can be downloaded from the gCube website:
${gcube.website}
Installation
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}
Documentation
--------------------------------------------------
Documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}
Support
--------------------------------------------------
Bugs and support requests can be reported in the gCube issue tracking tool:
${gcube.issueTracking}
Licensing
--------------------------------------------------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID></ID>
<Type>Library</Type>
<Profile>
<Description>${description}</Description>
<Class>Portal</Class>
<Name>${artifactId}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Files>
<File>${build.finalName}.war</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/_build/

20
docs/Makefile Normal file
View File

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

55
docs/conf.py Normal file
View File

@ -0,0 +1,55 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'Social Service'
copyright = '2022, Massimiliano Assante (ISTI-CNR)'
author = 'Massimiliano Assante (ISTI-CNR)'
# The full version, including alpha/beta/rc tags
release = '2.7.0'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

115
docs/index.rst Normal file
View File

@ -0,0 +1,115 @@
.. Social Service Client documentation master file, created by
sphinx-quickstart on Tue Aug 2 16:11:12 2022.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Social Service's documentation!
=================================================
The Social Service is a RESTful application which exposes operations coming from both the gCube `Social-Networking-Library <https://wiki.gcube-system.org/gcube/Social_Networking_Library>`_
and the `User Management <https://wiki.gcube-system.org/gcube/UserManagement_Core>`_ components.
The former is the bridge between the Cassandra Cluster (on which social data are stored) and the social applications,
whereas the latter is the abstraction layer over the enabling technology for the Identity and Access Management service, in terms of: roles, users and
organizations and how they are mapped to D4Science concepts.
The web services exposes a subset of such functionalities over **https in a standard, reliable and secure way**.
See the vailable REST-API at a glance on `its API docs <../api-docs/index.html>`_.
Base URL
==================
In the production environment, its current value is https://api.d4science.org/rest
Authorization (how to contact the service)
==================
D4Science adopts state-of-the-art industry standards for authentication and authorization.
Specifically, the implementation fully adopts `OIDC (OpenID Connect) <https://openid.net/connect>`_ for authentication and UMA 2 (User Managed Authorization) for authorization flows.
`JSON Web Token (JWT) Access token <https://jwt.io/>`_ are used for both authentication and authorization.
Obtain your Bearer token here: https://dev.d4science.org/how-to-access-resources
Java Client
==================
The methods of the Web Service can be called by writing your own REST client application or by using already existing REST client plugins. We provide the following Java Client out-of-the-box.
.. TIP::
If you're coding in Java it is recommended that you use this Java Client.
**Maven Coordinates**
.. code:: xml
<groupId>org.gcube.social-networking</groupId>
<artifactId>social-service-client</artifactId>
<version>[1.1.0, 2.0.0)</version>
**Methods Result**
The service exposes `its methods <../api-docs/index.html>`_ using a standard naming approach. Moreover, they accept (in case of http POST/PUT methods) JSON objects.
.. IMPORTANT::
The result of all methods is always a JSON object as per below:
.. code:: javascript
{
"success": false/true,
"message": ...,
"result": ...,
}
Where
- success reports if the request succeeded or failed;
- message is a status/error message that can be checked in case of errors (success equals false);
-result is the current result object (it can be a list, a single object and so on depending on the invoked method).
*Inputs are automatically validated before the request is served.*
**Usage examples**
- Send a Message
.. code:: java
import org.gcube.social_networking.social_networking_client_library.MessageClient;
import org.gcube.social_networking.socialnetworking.model.beans.Message;
import org.gcube.social_networking.socialnetworking.model.beans.Recipient;
//send
MessageClient messagesClient = new MessageClient();
List<Recipient> rec = Arrays.asList(new Recipient("andrea.rossi"));
Message message = new Message(
"Test message",
"Sending message via client " + System.currentTimeMillis(),
new ArrayList<Recipient>(rec));
String idMessage = messagesClient.writeMessage(message);
- Get User Profile
.. code:: java
import org.gcube.social_networking.social_networking_client_library.PeopleClient;
PeopleClient getProfile = new PeopleClient();
UserProfile profile = getProfile.getProfile();
logger.debug("Profile retrieved is " + profile);
- Get Posts in a VRE
.. code:: java
import org.gcube.social_networking.social_networking_client_library.PostClient;
PostClient postClient = new PostClient();
List<Feed> vrePosts = postClient.getPostsVRE();
logger.debug("VRE posts are " + vrePosts);

35
docs/make.bat Normal file
View File

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

37
enunciate.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<enunciate
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.14.0.xsd">
<api-classes>
<include
pattern="org.gcube.portal.social.networking.**"/>
<include
pattern="org.gcube.social_networking.socialnetworking.model.beans.**"/>
<exclude
pattern="org.gcube.portal.social.networking.ws.docs.DocsGenerator" />
</api-classes>
<modules>
<jackson1 disabled="true" />
<gwt-json-overlay disabled="true" />
<php-json-client disabled="true" />
<ruby-json-client disabled="true" />
<java-json-client disabled="true" />
<!-- <java-json-client jarName="social-service-client.jar" -->
<!-- bundleSourcesWithClasses="true" groupId="org.gcube.social-networking" -->
<!-- artifactId="auto-social-client" javac-source="1.8" javac-target="1.8"> -->
<!-- <package-conversions> -->
<!-- <convert -->
<!-- from="org.gcube.portal.social.networking.ws" -->
<!-- to="org.gcube.social.client" /> -->
<!-- </package-conversions> -->
<!-- </java-json-client> -->
<javascript-client disabled="true" />
<docs docsDir="${project.build.directory}" docsSubdir="api-docs" />
<docs
freemarkerTemplate="${project.basedir}/src/main/resources/META-INF/enunciate/d4science_docs.fmt">
<additional-css
file="css/d4science_enunciate_custom.css" />
</docs>
<swagger basePath="/rest" />
</modules>
</enunciate>

326
pom.xml
View File

@ -12,50 +12,92 @@
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library-ws</artifactId>
<packaging>war</packaging>
<version>2.3.0</version>
<version>3.0.0-SNAPSHOT</version>
<name>social-networking-library-ws</name>
<description>Rest interface for the social networking library.</description>
<properties>
<java-version>1.8</java-version>
<version.swagger>1.5.13</version.swagger>
<version.jersey>2.25.1</version.jersey>
<distroDirectory>${project.basedir}/distro</distroDirectory>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<enunciate.version>2.14.0</enunciate.version>
<cassandra.driver.oss.version>4.13.0</cassandra.driver.oss.version>
<jackson.version>2.12.6</jackson.version>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<distroDirectory>distro</distroDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<scm>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/social-networking-library-ws.git</connection>
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/social-networking-library-ws.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/social-networking-library-ws</url>
<connection>
scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</connection>
<developerConnection>
scm:git:https://code-repo.d4science.org/gCubeSystem/${project.artifactId}.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/${project.artifactId}</url>
</scm>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-smartgears-bom</artifactId>
<version>LATEST</version>
<artifactId>gcube-smartgears-bom</artifactId>
<version>2.1.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.7</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- enunciate deps -->
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
<version>${enunciate.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-rt-util</artifactId>
<version>${enunciate.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- end enunciate deps -->
<dependency>
<groupId>org.gcube.social-networking</groupId>
<artifactId>social-service-model</artifactId>
<version>[1.2.0-SNAPSHOT, 2.0.0)</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId>
<version>[1.0.1,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.common.portal</groupId>
<artifactId>portal-manager</artifactId>
<version>[2.4.1-SNAPSHOT,3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-client-library</artifactId>
<!-- <version>2.0.0-SNAPSHOT</version> -->
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
@ -85,54 +127,6 @@
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>jersey-client</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-bundle</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-apache-client4</artifactId>
<groupId>com.sun.jersey.contribs</groupId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-thrift</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-cassandra</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.netflix.astyanax</groupId>
<artifactId>astyanax-core</artifactId>
<version>2.0.2</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.gcube.socialnetworking</groupId>
<artifactId>social-util-library</artifactId>
@ -142,7 +136,7 @@
<dependency>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<version>[2.0.0, 3.0.0)</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -167,16 +161,10 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>home-library</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>home-library-jcr</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
@ -190,26 +178,78 @@
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>21.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-smile</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<version>2.8.6</version>
</dependency>
<dependency>
<artifactId>jackson-dataformat-cbor</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<version>2.8.6</version>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Please note that the elasticsearch client needs a compress-lzf version
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-cbor</artifactId>
<version>2.8.6</version>
</dependency>
<!-- needed by the search-->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-query-builder</artifactId>
<version>${cassandra.driver.oss.version}</version>
</dependency>
<dependency>
<groupId>com.datastax.oss</groupId>
<artifactId>java-driver-mapper-runtime</artifactId>
<version>${cassandra.driver.oss.version}</version>
</dependency>
<dependency>
<groupId>com.google</groupId>
<artifactId>gwt-jsonmaker</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- Please note that the elasticsearch client needs a compress-lzf
version
>= 1.0.2 -->
<dependency>
<groupId>com.ning</groupId>
@ -219,46 +259,25 @@
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<!-- if your container implements Servlet API older than 3.0, use
"jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet-core</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-processing</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>${version.swagger}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>jackson-dataformat-yaml</artifactId>
<groupId>com.fasterxml.jackson.dataformat</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.portlet</groupId>
@ -288,79 +307,106 @@
<dependency>
<groupId>org.gcube.applicationsupportlayer</groupId>
<artifactId>aslsocial</artifactId>
<version>[1.7.1-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<version>[1.8.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3</version>
<scope>compile</scope>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>6.1.22</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<finalName>${name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<groupId>kr.motd.maven</groupId>
<artifactId>sphinx-maven-plugin</artifactId>
<version>2.10.0</version>
<configuration>
<outputDirectory>
${project.build.directory}/${project.artifactId}-${project.version}/docs</outputDirectory>
<builder>html</builder>
<configDirectory>${basedir}/docs</configDirectory>
<sourceDirectory>${basedir}/docs</sourceDirectory>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<phase>process-resources</phase>
<goals>
<goal>exploded</goal>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
<!-- Enunciate Maven plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-maven-plugin</artifactId>
<version>${enunciate.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- SA Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>descriptor.xml</descriptor>
</descriptors>
<sourcepath-includes>
<sourcepath-include>
<!-- Include the "com.external:external" artifact on
the sourcepath. -->
<groupId>org.gcube.social-networking</groupId>
<artifactId>social-service-model</artifactId>
</sourcepath-include>
<sourcepath-include>
<groupId>org.gcube.portal</groupId>
<artifactId>social-networking-library</artifactId>
</sourcepath-include>
</sourcepath-includes>
</configuration>
<executions>
<execution>
<id>servicearchive</id>
<phase>install</phase>
<id>assemble</id>
<goals>
<goal>single</goal>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
<!-- Copy Enunciate Documentation from your-application/docs to
your-application.war -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
<additionalJOption>-Xdoclint:none</additionalJOption>
</configuration>
<version>3.1.0</version>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>generate-doc</id>
<phase>install</phase>
<id>copy-enunciate-docs</id>
<phase>process-resources</phase>
<goals>
<goal>jar</goal>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<targetPath>
${project.build.directory}/${project.artifactId}-${project.version}/api-docs</targetPath>
<directory>
${project.build.directory}/api-docs</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

View File

@ -30,7 +30,7 @@ public class GroupsCache {
/**
* Retrieve an entry
* @param id
* @param groupId
* @return user associated to the user
*/
public GCubeGroup getGroup(long groupId){
@ -44,7 +44,7 @@ public class GroupsCache {
/**
* Save an entry into the cache
* @param id
* @param user
* @param group
*/
public void pushEntry(long id, GCubeGroup group){
Ehcache groupsCache = CachesManager.getCache(CachesManager.GROUPS_CACHE);

View File

@ -90,11 +90,11 @@ public class SocialNetworkingSiteFinder {
if(scope == null || scope.isEmpty())
throw new IllegalArgumentException("Scope cannot be null/empty");
if(socialSitesCache.get(scope) != null)
if(socialSitesCache != null && socialSitesCache.get(scope) != null)
return (SocialNetworkingSite) socialSitesCache.get(scope).getObjectValue();
else{
SocialNetworkingSite site = discoverSite(scope);
if(site != null)
if(socialSitesCache != null && site != null)
socialSitesCache.put(new Element(scope, site));
return site;
}
@ -209,7 +209,7 @@ public class SocialNetworkingSiteFinder {
}
private static boolean isDevOrPreprod(String rootContext) {
return rootContext.equals("/gcube");
return (rootContext.equals("/gcube") || rootContext.equals("/pred4s"));
}
/**

View File

@ -59,7 +59,7 @@ public class UsersCache{
/**
* Retrieve an entry
* @param id
* @param userId
* @return user associated to the user
*/
public GCubeUser getUser(long userId){

View File

@ -0,0 +1,143 @@
package org.gcube.portal.social.networking.liferay.ws;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KeycloakAPICredentials {
private static final Logger logger = LoggerFactory.getLogger(KeycloakAPICredentials.class);
// the singleton obj
private static KeycloakAPICredentials singleton = new KeycloakAPICredentials();
// properties that it contains
private String keycloakURL;
private String realm;
private String clientid;
private String password;
// Service endpoint properties
private final static String RUNTIME_RESOURCE_NAME = "IAM";
private final static String CATEGORY = "Service";
/**
* Private constructor
*/
private KeycloakAPICredentials() {
logger.info("Building KeycloakAPICredentials object");
lookupPropertiesFromIs();
logger.info("KeycloakAPICredentials object built");
}
/**
* Read the properties from the infrastructure
*/
private void lookupPropertiesFromIs() {
logger.info("Starting creating KeycloakAPICredentials");
String oldContext = ScopeProvider.instance.get();
ApplicationContext ctx = ContextProvider.get(); // get this info from SmartGears
ScopeProvider.instance.set("/"+ctx.container().configuration().infrastructure());
logger.info("Discovering liferay user's credentials in context " + ctx.container().configuration().infrastructure());
try{
List<ServiceEndpoint> resources = getConfigurationFromIS();
if (resources.size() == 0){
logger.error("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
throw new Exception("There is no Runtime Resource having name " + RUNTIME_RESOURCE_NAME +" and Category " + CATEGORY + " in this scope.");
}
else {
for (ServiceEndpoint res : resources) {
Iterator<AccessPoint> accessPointIterator = res.profile().accessPoints().iterator();
while (accessPointIterator.hasNext()) {
ServiceEndpoint.AccessPoint accessPoint = (ServiceEndpoint.AccessPoint) accessPointIterator
.next();
if(accessPoint.name().equals("d4science")){
keycloakURL = accessPoint.address();
realm = accessPoint.name();
clientid = accessPoint.username();
password = StringEncrypter.getEncrypter().decrypt(accessPoint.password());
logger.info("Found accesspoint URL = " + keycloakURL);
}
}
}
}
}catch(Exception e){
logger.error("Unable to retrieve such service endpoint information!", e);
return;
}finally{
if(oldContext != null)
ScopeProvider.instance.set(oldContext);
}
logger.info("Bean built " + toString());
}
/**
* Retrieve endpoints information from IS for DB
* @return list of endpoints for ckan database
* @throws Exception
*/
private List<ServiceEndpoint> getConfigurationFromIS() throws Exception{
SimpleQuery query = queryFor(ServiceEndpoint.class);
query.addCondition("$resource/Profile/Name/text() eq '"+ RUNTIME_RESOURCE_NAME +"'");
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
List<ServiceEndpoint> toReturn = client.submit(query);
return toReturn;
}
public static KeycloakAPICredentials getSingleton() {
if (singleton == null)
singleton = new KeycloakAPICredentials();
return singleton;
}
public String getServerURL() {
return keycloakURL;
}
public String getClientid() {
return clientid;
}
public String getPassword() {
return password;
}
public String getRealm() {
return realm;
}
@Override
public String toString() {
return "KeycloakAPICredentials [keycloakURL=" + keycloakURL + ", realm=" + realm + ", clientid=" + clientid
+ ", password=**************]";
}
}

View File

@ -7,7 +7,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;

View File

@ -1,31 +0,0 @@
package org.gcube.portal.social.networking.swagger.config;
import io.swagger.jaxrs.config.BeanConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
/**
* Configuration servlet for swagger.
* @author Costantino Perciante at ISTI-CNR
*/
@SuppressWarnings("serial")
public class Bootstrap extends HttpServlet{
public static final String GCUBE_TOKEN_IN_QUERY_DEF = "gcube-token-query";
public static final String GCUBE_TOKEN_IN_HEADER_DEF = "gcube-token-header";
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setResourcePackage("org.gcube.portal.social.networking.ws");
beanConfig.setPrettyPrint(true); // print pretty json
beanConfig.setHost("socialnetworking1.d4science.org");
beanConfig.setBasePath("social-networking-library-ws/rest");
beanConfig.setScan(true);
}
}

View File

@ -1,25 +0,0 @@
package org.gcube.portal.social.networking.swagger.config;
/**
* Swagger constants
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class SwaggerConstants {
public static final String SECURITY_SCHEMA = "gcube-token";
public static final String HTTP_SCHEMA = "http";
public static final String HTTPS_SCHEMA = "https";
// VALUES
public static final String USERS = "users";
public static final String TOKENS = "tokens";
public static final String POSTS = "posts";
public static final String PEOPLE = "people";
public static final String NOTIFICATIONS = "notifications";
public static final String MESSAGES = "messages";
public static final String HASHTAGS = "hashtags";
public static final String FULLTEXT = "full-text-search";
public static final String COMMENTS = "comments";
public static final String VRES = "vres";
}

View File

@ -1,47 +0,0 @@
package org.gcube.portal.social.networking.ws;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import io.swagger.annotations.ApiKeyAuthDefinition;
import io.swagger.annotations.ApiKeyAuthDefinition.ApiKeyLocation;
import io.swagger.annotations.Contact;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.ExternalDocs;
import io.swagger.annotations.Info;
import io.swagger.annotations.SecurityDefinition;
import io.swagger.annotations.SwaggerDefinition;
@SwaggerDefinition(
info = @Info(
description = "This is the official documentation of the second version (v. 2.0) of the Social-Networking RESTful interface.",
version = "V 2.0",
title = "Social Networking RESTful Service",
contact = @Contact(
name = "Costantino Perciante",
email ="costantino.perciante@isti.cnr.it"
),
extensions = {
@Extension(name = "extra-contact", properties = {
@ExtensionProperty(name = "name", value = "Massimiliano Assante"),
@ExtensionProperty(name = "email", value = "massimiliano.assante@isti.cnr.it")
}),
@Extension(name = "development-host", properties = {
@ExtensionProperty(name = "url", value = "https://socialnetworking-d-d4s.d4science.org"),
})
}
),
externalDocs=@ExternalDocs(url="https://wiki.gcube-system.org/gcube/Social_Networking_Service", value="Wiki page at gCube"),
host="socialnetworking1.d4science.org",
basePath="social-networking-library-ws/rest",
securityDefinition=@SecurityDefinition(
apiKeyAuthDefinitions={
@ApiKeyAuthDefinition(key=Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF, description="A token bound to a user (or app identifier) and a context", in=ApiKeyLocation.HEADER, name="gcube-token"),
@ApiKeyAuthDefinition(key=Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF, description="A token bound to a user (or app identifier) and a context", in=ApiKeyLocation.QUERY, name="gcube-token")
}),
schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}
)
public interface SNLApiConfig {
}

View File

@ -0,0 +1,50 @@
package org.gcube.portal.social.networking.ws.docs;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("api-docs")
public class DocsGenerator {
private static Logger logger = LoggerFactory.getLogger(DocsGenerator.class);
@GET
@Path("/{any: .*}")
public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException {
logger.info(DocsGenerator.class.getSimpleName() + " toDoc called");
String pathInfo = req.getPathInfo();
logger.debug("pathInfo {}", pathInfo);
try {
if (pathInfo.endsWith("/api-docs")) {
pathInfo += "index.html";
}
if (pathInfo.endsWith("/api-docs/")) {
pathInfo += "index.html";
}
logger.info("going to {}", pathInfo);
String realPath = req.getServletContext().getRealPath(pathInfo);
return new FileInputStream(new File(realPath));
} catch (Exception e) {
e.printStackTrace();
//MANAGE THE EXCEPTION
}
return null;
}
}

View File

@ -10,8 +10,7 @@ import org.slf4j.LoggerFactory;
/**
* Exception thrown when @Valid fail
* @author Costantino Perciante at ISTI-CNR
* Exception gets thrown when @Valid fail
*/
@Provider
public class ApplicationException implements ExceptionMapper<Exception> {
@ -19,7 +18,7 @@ public class ApplicationException implements ExceptionMapper<Exception> {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ApplicationException.class);
public Response toResponse(Exception e) {
logger.warn("ApplicationException invoked for exception " + e);
logger.warn("ApplicationException invoked for exception ", e);
return Response
.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode())
.type(MediaType.APPLICATION_JSON)

View File

@ -0,0 +1,16 @@
package org.gcube.portal.social.networking.ws.ex;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response.Status;
public class AuthException extends WebApplicationException {
/**
*
*/
private static final long serialVersionUID = 1L;
public AuthException(Throwable cause) {
super(cause, Status.FORBIDDEN);
}
}

View File

@ -1,8 +1,5 @@
package org.gcube.portal.social.networking.ws.inputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@ -13,18 +10,12 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* Application id object
* @author Costantino Perciante at ISTI-CNR
*/
@ApiModel(description="An object containing the app_id field", value="Application")
//@ApiModel(description="An object containing the app_id field", value="Application")
public class ApplicationId {
@JsonProperty("app_id")
@NotNull(message="app_id cannot be null")
@Size(message="app_id cannot be empty", min=1)
@ApiModelProperty(
example="appX",
name="app_id",
required=true,
value="The application identifier"
)
private String appId;
public ApplicationId() {

View File

@ -0,0 +1,72 @@
package org.gcube.portal.social.networking.ws.inputs;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.webcohesion.enunciate.metadata.DocumentationExample;
/**
* Generic input bean for methods that allow to comment posts
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
public class CommentInputBean implements Serializable{
private static final long serialVersionUID = 5274608088828232980L;
@JsonProperty("text")
@NotNull(message="text cannot be null")
@Size(min=1, message="text cannot be empty")
@DocumentationExample("I would like to comment that ...")
/**
* text the text of the comment
*/
private String text;
@NotNull(message="postid cannot be null")
@JsonProperty("postid")
/**
* postid the postid of the post where you attach the comment
*/
private String postid;
public CommentInputBean() {
super();
}
/**
* @param text
* @param postid
*/
public CommentInputBean(String text, String postid) {
super();
this.text = text;
this.postid = postid;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getPostid() {
return postid;
}
public void setPostid(String postid) {
this.postid = postid;
}
@Override
public String toString() {
return "CommentInputBean [text=" + text + ", postid=" + postid + "]";
}
}

View File

@ -1,164 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
import org.gcube.portal.databook.shared.JobStatusType;
import org.gcube.portal.databook.shared.RunningJob;
import org.gcube.portal.social.networking.ws.providers.JobStatusTypeDeserializer;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* The job notification bean class.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
@ApiModel(description="A job notification object", value="JobNotification")
public class JobNotificationBean {
@JsonProperty("recipient")
@NotNull(message="recipient cannot be missing")
@ApiModelProperty(value="The recipient of the notification",
required=true,
example="andrea.rossi",
name="recipient")
private String recipient;
@JsonProperty("job_id")
@ApiModelProperty(value="The job's identifier, i.e. very likely a UUID",
required=true,
example="88055f18-558a-4246-942d-a43012528c92",
name="job_id")
@NotNull(message="job_id cannot be missing")
private String jobId;
@JsonProperty("job_name")
@ApiModelProperty(value="The job's name",
required=true,
example="SocialDataIndexer Plugin",
name="job_name")
@NotNull(message="job_name cannot be missing")
private String jobName;
@JsonProperty("service_name")
@ApiModelProperty(value="The name of the service running the job",
required=true,
example="SmartExecutor",
name="service_name")
@NotNull(message="service_name cannot be missing")
private String serviceName;
@JsonProperty("status")
@ApiModelProperty(value="The status of the job",
required=true,
example="FAILED",
name="status",
allowableValues = "CANCELLED,CANCELLING,DELETED,DELETING,EXECUTING,FAILED,NEW,SUBMITTED,SUCCEEDED,TIMED_OUT,WAITING"
)
@JsonDeserialize(using=JobStatusTypeDeserializer.class)
@NotNull(message="status cannot be missing")
private JobStatusType status;
@JsonProperty("status_message")
@ApiModelProperty(value="A message reporting the reason of the current status",
required=false,
example="An error occurred while ...",
name="status_message")
private String statusMessage;
public JobNotificationBean() {
super();
}
/**
* @param recipient
* @param jobId
* @param jobName
* @param serviceName
* @param status
* @param statusMessage
*/
public JobNotificationBean(String recipient, String jobId, String jobName,
String serviceName, JobStatusType status, String statusMessage) {
super();
this.recipient = recipient;
this.jobId = jobId;
this.jobName = jobName;
this.serviceName = serviceName;
this.status = status;
this.statusMessage = statusMessage;
}
public String getStatusMessage() {
return statusMessage;
}
public void setStatusMessage(String statusMessage) {
this.statusMessage = statusMessage;
}
public String getRecipient() {
return recipient;
}
public void setRecipient(String recipient) {
this.recipient = recipient;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getJobId() {
return jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
public JobStatusType getStatus() {
return status;
}
public void setStatus(JobStatusType status) {
this.status = status;
}
public RunningJob getRunningJob(){
return new RunningJob(jobId, jobName, status, statusMessage, serviceName);
}
@Override
public String toString() {
return "JobNotificationBean ["
+ (recipient != null ? "recipient=" + recipient + ", " : "")
+ (jobId != null ? "jobId=" + jobId + ", " : "")
+ (jobName != null ? "jobName=" + jobName + ", " : "")
+ (serviceName != null ? "serviceName=" + serviceName + ", "
: "")
+ (status != null ? "status=" + status + ", " : "")
+ (statusMessage != null ? "statusMessage=" + statusMessage
: "") + "]";
}
}

View File

@ -0,0 +1,60 @@
package org.gcube.portal.social.networking.ws.inputs;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Like Bean object
*/
public class LikeInputBean {
@JsonProperty("likeid")
@NotNull(message="likeid cannot be null")
@Size(message="likeid cannot be empty", min=1)
private String likeid;
@JsonProperty("postid")
@NotNull(message="postid cannot be null")
@Size(message="postid cannot be empty", min=1)
private String postid;
public LikeInputBean() {
super();
}
/**
* @param likeid
* @param postid
*/
public LikeInputBean(String likeid, String postid) {
super();
this.likeid = likeid;
this.postid = postid;
}
public String getLikeid() {
return likeid;
}
public void setLikeid(String likeid) {
this.likeid = likeid;
}
public String getPostid() {
return postid;
}
public void setPostid(String postid) {
this.postid = postid;
}
@Override
public String toString() {
return "LikeInputBean [likeid=" + likeid + ", postid=" + postid + "]";
}
}

View File

@ -1,114 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.ArrayList;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Generic input bean for methods that allow to write messages
* @author Costantino Perciante at ISTI-CNR
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
@ApiModel(description="A message object", value="Message")
public class MessageInputBean implements Serializable {
private static final long serialVersionUID = -1317811686036127456L;
/*@JsonProperty("sender")
@ApiModelProperty(
example="andrea.rossi",
required=false,
hidden=true, // do not show this information
value="The sender of the message. If not specified is the gcube-token's owner")
private String sender;*/
@JsonProperty("body")
@NotNull(message="body cannot be missing")
@Size(min=1, message="body cannot be empty")
@ApiModelProperty(
example="This is the body of the mail ...",
required= true,
value="The body of the message")
private String body;
@JsonProperty("subject")
@NotNull(message="subject cannot be missing")
@Size(min=1, message="subject cannot be empty")
@ApiModelProperty(
example="This is the subject of the mail ...",
required= true,
value="The subject of the message")
private String subject;
@JsonProperty("recipients")
@NotNull(message="recipients cannot be missing")
@Size(min=1, message="at least a recipient is needed")
@Valid // validate recursively
@ApiModelProperty(
required= true,
value="The recipients of this message. At least one is needed")
private ArrayList<Recipient> recipients;
public MessageInputBean() {
super();
}
public MessageInputBean(String sender, String body, String subject,
ArrayList<Recipient> recipients) {
super();
//this.sender = sender;
this.body = body;
this.subject = subject;
this.recipients = recipients;
}
// public String getSender() {
// return sender;
// }
// public void setSender(String sender) {
// this.sender = sender;
// }
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public ArrayList<Recipient> getRecipients() {
return recipients;
}
public void setRecipients(ArrayList<Recipient> recipients) {
this.recipients = recipients;
}
@Override
public String toString() {
return "MessageInputBean ["
+ (body != null ? "body=" + body + ", " : "")
+ (subject != null ? "subject=" + subject + ", " : "")
+ (recipients != null ? "recipients=" + recipients : "") + "]";
}
// @Override
// public String toString() {
// return "MessageInputBean [sender=" + sender + ", body=" + body
// + ", subject=" + subject + ", recipients=" + recipients + "]";
// }
}

View File

@ -0,0 +1,43 @@
package org.gcube.portal.social.networking.ws.inputs;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Application id object
*/
public class PostId {
@JsonProperty("postid")
@NotNull(message="postid cannot be null")
@Size(message="postid cannot be empty", min=1)
private String postId;
public PostId() {
super();
}
public PostId(String postId) {
super();
this.postId = postId;
}
public String getPostId() {
return postId;
}
public void setPostId(String postId) {
this.postId = postId;
}
@Override
public String toString() {
return "PostId [postid=" + postId + "]";
}
}

View File

@ -1,8 +1,5 @@
package org.gcube.portal.social.networking.ws.inputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
@ -10,12 +7,12 @@ import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.webcohesion.enunciate.metadata.DocumentationExample;
/**
* Generic input bean for methods that allow to write posts
* @author Costantino Perciante at ISTI-CNR
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
@ApiModel(description="A post object", value="Post")
public class PostInputBean implements Serializable{
private static final long serialVersionUID = 5274608088828232980L;
@ -23,58 +20,36 @@ public class PostInputBean implements Serializable{
@JsonProperty("text")
@NotNull(message="text cannot be null")
@Size(min=1, message="text cannot be empty")
@ApiModelProperty(
example="Dear vre members, ...",
required=true,
value="The text of the post")
@DocumentationExample("Dear vre members, ...")
/**
* text the text of the post
*/
private String text;
@JsonProperty("preview_title")
@ApiModelProperty(
required=false,
value="A preview title for the preview",
name="preview_title")
private String previewtitle;
@JsonProperty("preview_description")
@ApiModelProperty(
required=false,
value="A preview description for the preview",
name="preview_description")
private String previewdescription;
@JsonProperty("preview_host")
@ApiModelProperty(
required=false,
value="A preview host for the preview",
name="preview_host")
private String previewhost;
@JsonProperty("preview_url")
@ApiModelProperty(
required=false,
value="A preview url for the preview",
name="preview_url")
private String previewurl;
/**
* param httpimageurl An image url for the preview"
*/
@JsonProperty("image_url")
@ApiModelProperty(
required=false,
value="An image url for the preview",
name="image_url")
private String httpimageurl;
/**
* enablenotification If true send a notification to the other vre members about this post
*/
@JsonProperty("enable_notification")
@ApiModelProperty(
required=false,
value="If true send a notification to the other vre members about this post",
name="enable_notification")
private boolean enablenotification;
@JsonProperty("params")
@ApiModelProperty(
required=false,
value="Other parameters for the application's posts")
private String params;
public PostInputBean() {

View File

@ -1,52 +0,0 @@
package org.gcube.portal.social.networking.ws.inputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Recipient message bean
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
*/
@JsonIgnoreProperties(ignoreUnknown = true) // ignore in serialization/deserialization
@ApiModel(description="A recipient object")
public class Recipient implements Serializable{
private static final long serialVersionUID = 1071412144446514138L;
@JsonProperty("id")
@NotNull(message="recipient id must not be null")
@Size(min=1, message="recipient id must not be empty")
@ApiModelProperty(
example="andrea.rossi",
required=true,
value="The id of the recipient")
private String id;
public Recipient() {
super();
}
public Recipient(String id) {
super();
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Recipient [id=" + id + "]";
}
}

View File

@ -0,0 +1,63 @@
package org.gcube.portal.social.networking.ws.inputs;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
*
*
*/
public class UserSetNotificationBean {
@JsonProperty("username")
@NotNull(message="username cannot be null")
@Size(message="username cannot be empty", min=1)
private String username;
@JsonProperty("disableNotification")
@NotNull(message="disableNotification cannot be null")
private Boolean disableNotification;
public UserSetNotificationBean() {
super();
}
/**
* @param username
* @param disableNotification
*/
public UserSetNotificationBean(String username, boolean disableNotification) {
super();
this.username = username;
this.disableNotification = disableNotification;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isDisableNotification() {
return disableNotification;
}
public void setDisableNotification(boolean disableNotification) {
this.disableNotification = disableNotification;
}
@Override
public String toString() {
return "UserSetNotificationBean [username=" + username + ", disableNotification=" + disableNotification + "]";
}
}

View File

@ -0,0 +1,28 @@
package org.gcube.portal.social.networking.ws.mappers;
import org.gcube.portal.databook.shared.NotificationType;
import org.gcube.portal.databook.shared.ex.NotificationTypeNotFoundException;
import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEventType;
public class CatalogueEventTypeMapper {
public CatalogueEventTypeMapper() {
}
public static NotificationType getType(CatalogueEventType type) throws NotificationTypeNotFoundException {
switch (type) {
case ITEM_PUBLISHED:
return NotificationType.CAT_ITEM_PUBLISHED;
case ITEM_REJECTED:
return NotificationType.CAT_ITEM_REJECTED;
case ITEM_REMOVED:
return NotificationType.CAT_ITEM_DELETE;
case ITEM_SUBMITTED:
return NotificationType.CAT_ITEM_SUBMITTED;
case ITEM_UPDATED:
return NotificationType.CAT_ITEM_UPDATED;
default:
throw new NotificationTypeNotFoundException("The Catalogue event could not be mapped");
}
}
}

View File

@ -0,0 +1,64 @@
package org.gcube.portal.social.networking.ws.mappers;
import org.gcube.portal.databook.shared.JobStatusType;
import org.gcube.portal.databook.shared.RunningJob;
import org.gcube.social_networking.socialnetworking.model.beans.JobNotificationBean;
import org.gcube.social_networking.socialnetworking.model.beans.JobStatusModelType;
public class JobMapper {
public JobMapper() {
}
public static RunningJob getJob(JobNotificationBean item) {
String jobId = null;
String jobName = null;
JobStatusType status = null;
String message = null;
String serviceName = null; // i.e., Dataminer, SmartExecutor..
try {
jobId = item.getJobId();
jobName = item.getJobName();
status = getType(item.getStatus());
message = item.getStatusMessage();
serviceName = item.getServiceName();
} catch (Exception e) {
e.printStackTrace();
}
return new RunningJob(jobId, jobName, status, message, serviceName);
}
public static JobStatusType getType(JobStatusModelType type) {
JobStatusType toReturn = null;
switch (type) {
case CANCELLED:
return JobStatusType.CANCELLED;
case DELETED:
return JobStatusType.DELETED;
case FAILED:
return JobStatusType.FAILED;
case CANCELLING:
return JobStatusType.CANCELLING;
case DELETING:
return JobStatusType.DELETING;
case EXECUTING:
return JobStatusType.EXECUTING;
case NEW:
return JobStatusType.NEW;
case SUBMITTED:
return JobStatusType.SUBMITTED;
case SUCCEEDED:
return JobStatusType.SUCCEEDED;
case TIMED_OUT:
return JobStatusType.TIMED_OUT;
case WAITING:
return JobStatusType.WAITING;
default:
break;
}
return toReturn;
}
}

View File

@ -0,0 +1,57 @@
package org.gcube.portal.social.networking.ws.mappers;
import org.gcube.applicationsupportlayer.social.shared.SocialFileItem;
import org.gcube.applicationsupportlayer.social.shared.SocialSharedFolder;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FileItemBean;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderBean;
public class WorkspaceItemMapper {
public WorkspaceItemMapper() {
// TODO Auto-generated constructor stub
}
public static SocialFileItem getFileItem(FileItemBean item) {
String id = null;
String name= null;
String title= null;
String path= null;
SocialSharedFolder parent = null;
try {
id = item.getId();
name = item.getName();
title = item.getTitle();
path = item.getPath();
parent = getSharedFolder(item.getParent());
} catch (Exception e) {
e.printStackTrace();
}
SocialFileItem toReturn = new SocialFileItem(id, name, title, path, parent);
return toReturn;
}
public static SocialSharedFolder getSharedFolder(FolderBean item) {
String id = null;
String name= null;
String title= null;
String displayName= null;
String path= null;
String parentId= null;
boolean vreFolder = false;
try {
id = item.getId();
name = item.getName();
title = item.getTitle();
displayName = item.getDisplayName();
path = item.getPath();
parentId = item.getParentId();
vreFolder = item.isVreFolder();
} catch (Exception e) {
e.printStackTrace();
}
SocialSharedFolder toReturn = new SocialSharedFolder(id, name, title, displayName, path, parentId, vreFolder);
return toReturn;
}
}

View File

@ -1,146 +0,0 @@
package org.gcube.portal.social.networking.ws.methods.v1;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.homelibrary.home.HomeLibrary;
import org.gcube.common.homelibrary.home.workspace.Workspace;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.notifications.bean.GenericItemBean;
import org.gcube.portal.notifications.thread.MessageNotificationsThread;
import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
/**
* Messages services REST interface
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
@Path("/messages")
@Deprecated
public class Messages {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Messages.class);
// recipients separator
private static final String RECIPIENTS_ID_SEPARATOR = ",";
// user manager
private UserManager uManager = null;
/**
* Build usermanager
* @throws Exception
*/
public Messages() throws Exception {
uManager = UserManagerWSBuilder.getInstance().getUserManager();
}
@POST
@Path("writeMessageToUsers/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Try to send a message to recipientsIds. The sender is the owner of the gcube-token if not otherwise stated.
* @param body
* @param subject
* @return ok on success, error otherwise
*/
public Response writeMessageToUsers(
@FormParam("sender") String sender, // the optional sender, if missing the sender will be the token's owner.
@FormParam("body") String body,
@FormParam("subject") String subject,
@FormParam("recipients") String recipientsIds) {
if(body == null || body.isEmpty() || subject == null || subject.isEmpty() || recipientsIds == null || recipientsIds.isEmpty()){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String senderId = caller.getClient().getId();
String scope = ScopeProvider.instance.get();
// check on sender id
if(sender == null || sender.isEmpty())
logger.info("Sender is going to be the token's owner [" + senderId + "]");
else{
logger.info("Sender is going to be " + sender);
senderId = sender;
}
// get the recipients ids (simple check, trim)
List<String> recipientsListFiltered = new ArrayList<String>();
String[] splittedRecipientsIds = recipientsIds.split(RECIPIENTS_ID_SEPARATOR);
List<GenericItemBean> recipientsBeans = new ArrayList<GenericItemBean>();
for (String recipientId : splittedRecipientsIds) {
try{
String tempId = recipientId.trim();
if(tempId.isEmpty())
continue;
GCubeUser userRecipient = uManager.getUserByUsername(tempId);
GenericItemBean beanUser = new GenericItemBean(userRecipient.getUsername(), userRecipient.getUsername(), userRecipient.getFullname(), userRecipient.getUserAvatarURL());
recipientsBeans.add(beanUser);
recipientsListFiltered.add(tempId);
}catch(Exception e){
logger.error("Unable to retrieve recipient information for recipient with id " + recipientId, e);
}
}
if(recipientsListFiltered.isEmpty()){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.BAD_REQUEST).build();
}
try{
logger.info("Trying to send message with body " + body + " subject " + subject + " to user " + recipientsIds + " from " + senderId);
// sender info
GCubeUser senderUser = uManager.getUserByUsername(senderId);
Workspace workspace = HomeLibrary.getUserWorkspace(senderId);
// send message
logger.debug("Sending message to " + recipientsListFiltered);
String messageId = workspace.getWorkspaceMessageManager()
.sendMessageToPortalLogins(subject, body,
new ArrayList<String>(), recipientsListFiltered);
// send notification
logger.debug("Message sent to " + recipientsIds + ". Sending message notification to: " + recipientsIds);
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(scope);
SocialNetworkingUser user = new SocialNetworkingUser(
senderUser.getUsername(), senderUser.getEmail(),
senderUser.getFullname(), senderUser.getUserAvatarURL());
logger.info("SocialNetworkingUser is " + user);
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, scope, user);
new Thread(new MessageNotificationsThread(recipientsBeans, messageId, subject, body, nm)).start();
}catch(Exception e){
logger.error("Unable to send message.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Status.CREATED).build();
}
}

View File

@ -1,67 +0,0 @@
package org.gcube.portal.social.networking.ws.methods.v1;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.portal.databook.shared.Notification;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.slf4j.LoggerFactory;
/**
* REST interface for the social networking library (notifications).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("/notifications")
@Deprecated
public class Notifications {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Notifications.class);
@GET
@Path("getRangeNotificationsByUser/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves notifications from from up to a given quantity for a given user (to whom the token belongs)
* @param from
* @param quantity
* @param token
* @return
*/
public Response getRangeNotificationsByUser(
@QueryParam("from") int from,
@QueryParam("quantity") int quantity) {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.info("Retrieving " + quantity + " notifications of user = " + username + " from " + from);
if(from <= 0 || quantity <= 0){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.BAD_REQUEST).build();
}
List<Notification> notifications = null;
try{
notifications = CassandraConnection.getInstance().getDatabookStore().getRangeNotificationsByUser(username, from, quantity);
}catch(Exception e){
logger.error("Unable to retrieve such notifications.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
logger.info("List of notifications retrieved");
return Response.status(Status.OK).entity(notifications).build();
}
}

View File

@ -1,436 +0,0 @@
package org.gcube.portal.social.networking.ws.methods.v1;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.Filters;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.slf4j.LoggerFactory;
/**
* REST interface for the social networking library (feeds).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("/posts")
@Deprecated
public class Posts {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Posts.class);
@GET
@Path("getRecentPostsByUserAndDate/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves the most recent posts of the token's owner (starting from timeInMillis)
* @param timeInMillis
* @return Response (OK, BAD REQUEST, ...)
*/
public Response getRecentPostsByUserAndDate(
@QueryParam("time") long timeInMillis) {
if(timeInMillis < 0){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
List<Feed> feeds = null;
try{
logger.info("Retrieving feeds for user id " + username + " and reference time " + timeInMillis);
feeds = CassandraConnection.getInstance().getDatabookStore().getRecentFeedsByUserAndDate(username, timeInMillis);
Filters.filterFeedsPerContext(feeds, context);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
return Response.status(Status.NOT_FOUND).build();
}
logger.info("List retrieved");
return Response.status(Status.OK).entity(feeds).build();
}
@GET
@Path("getAllPostsByUser/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves all posts belong to token's owner
* @return Response (OK, BAD REQUEST, ...)
*/
public Response getAllPostsByUser() {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
List<Feed> feeds = null;
try{
logger.info("Retrieving feeds for user with id " + username);
feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByUser(username);
Filters.filterFeedsPerContext(feeds, context);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
return Response.status(Status.NOT_FOUND).build();
}
logger.info("List retrieved");
return Response.status(Status.OK).entity(feeds).build();
}
@GET
@Path("getRecentPostsByUser/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves the last quantity posts belonging to token's owner
* @param quantity
* @param token
* @return Response (OK, BAD REQUEST, ...)
*/
public Response getRecentPostsByUser(
@DefaultValue("10") @QueryParam("quantity") int quantity) {
if(quantity < 0){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
List<Feed> feeds = null;
// if quantity is zero, just return an empty list
if(quantity == 0){
return Response.status(Status.OK).entity(feeds).build();
}
try{
logger.info("Retrieving last " + quantity + " feeds made by user " + username);
feeds = CassandraConnection.getInstance().getDatabookStore().getRecentFeedsByUser(username, -1);
Filters.filterFeedsPerContext(feeds, context);
feeds = feeds.subList(0, quantity);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
return Response.status(Status.NOT_FOUND).build();
}
logger.info("List retrieved");
return Response.status(Status.OK).entity(feeds).build();
}
@POST
@Consumes("application/x-www-form-urlencoded")
@Path("writePostUser")
@Produces(MediaType.TEXT_PLAIN)
/**
* Allows a user to write post
* @param feedText
* @param previewTitle
* @param previewDescription
* @param previewHost
* @param previewUrl
* @param httpImageUrl
* @param enableNotification
* @param token
* @return
*/
public Response writePostUser(
@FormParam("text") String feedText,
@FormParam("previewtitle")String previewTitle,
@FormParam("previewdescription") String previewDescription,
@FormParam("previewhost") String previewHost,
@FormParam("previewurl") String previewUrl,
@FormParam("httpimageurl") String httpImageUrl,
@DefaultValue("false") @FormParam("enablenotification") String enableNotification
){
logger.info("Request of writing a feed coming from user");
// at least the feedText is necessary to write a feed (the token is needed anyway)
if(feedText == null || feedText.isEmpty()){
logger.error("Missing request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
try{
// check it is a VRE
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
long groupId = groupManager.getGroupIdFromInfrastructureScope(context);
boolean isVRE = groupManager.isVRE(groupId);
if(!isVRE){
logger.error("A post cannot be written into a context that is not a VRE");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.POST_OUTSIDE_VRE).build();
}
// convert enablenotification parameter
boolean notifyGroup = enableNotification.equals("true");
if(notifyGroup)
logger.info("Enable notification for this user post.");
else
logger.info("Disable notification for this user post.");
// try to share
logger.debug("Trying to share user feed...");
Feed res = SocialUtils.shareUserUpdate(
username,
feedText,
ScopeProvider.instance.get(),
previewTitle,
previewDescription,
previewHost,
previewUrl,
httpImageUrl,
notifyGroup
);
if(res != null){
logger.info("Feed correctly written by user " + username);
return Response.status(Status.CREATED).build();
}
}catch(Exception e){
logger.error("Feed not written by user " + username, e);
}
logger.info("Feed not written by user " + username);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
@GET
@Path("getAllPostsByApp/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves all application's posts.
* @param token
* @return
*/
public Response getAllPostsByApp() {
Caller caller = AuthorizationProvider.instance.get();
String appId = caller.getClient().getId();
String context = ScopeProvider.instance.get();
// check if the token actually matches an application
ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, ScopeProvider.instance.get());
if(appProfile == null){
logger.error("The given token is not belonging to an application!!!");
return Response.status(Status.FORBIDDEN).entity(ErrorMessages.NOT_APP_TOKEN).build();
}
List<Feed> feeds = null;
try{
logger.info("Retrieving feeds for app with id " + appId);
feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByApp(appId);
Filters.filterFeedsPerContext(feeds, context);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
return Response.status(Status.NOT_FOUND).build();
}
logger.info("List retrieved");
return Response.status(Status.OK).entity(feeds).build();
}
@POST
@Consumes("application/x-www-form-urlencoded")
@Path("writePostApplication")
@Produces(MediaType.TEXT_PLAIN)
/**
* Allows an application to write a post.
* @param feedText
* @param uriParams
* @param previewTitle
* @param previewDescription
* @param httpImageUrl
* @param enableNotification
* @param token
* @return
*/
public Response writePostApp(
@FormParam("text") String feedText,
@FormParam("params") String uriParams,
@FormParam("previewtitle")String previewTitle,
@FormParam("previewdescription") String previewDescription,
@FormParam("httpimageurl") String httpImageUrl,
@DefaultValue("false") @FormParam("enablenotification") String enableNotification
){
logger.info("Request of writing a feed coming from an application.");
// at least the feedText is necessary to write a feed (the token is needed anyway)
if(feedText == null || feedText.isEmpty()){
logger.error("Missing request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String appId = caller.getClient().getId();
String context = ScopeProvider.instance.get();
try{
// check it is a VRE
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
long groupId = groupManager.getGroupIdFromInfrastructureScope(context);
boolean isVRE = groupManager.isVRE(groupId);
if(!isVRE){
logger.error("A post cannot be written into a context that is not a VRE");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.POST_OUTSIDE_VRE).build();
}
// check if the token actually matches an application profile
ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, ScopeProvider.instance.get());
if(appProfile == null){
logger.error("The given token doesn't belong to an application!!!");
return Response.status(Status.FORBIDDEN).entity(ErrorMessages.NOT_APP_TOKEN).build();
}
// convert enablenotification parameter
boolean notifyGroup = enableNotification.equals("true");
if(notifyGroup)
logger.info("Enable notification for this application post.");
else
logger.info("Disable notification for this application post.");
// write feed + notification if it is the case
Feed written = SocialUtils.shareApplicationUpdate(
feedText,
uriParams,
previewTitle,
previewDescription,
httpImageUrl,
appProfile,
caller,
notifyGroup
);
if(written != null){
return Response.status(Status.CREATED).build();
}
}catch(Exception e){
logger.error("Error while writing a post", e);
}
logger.info("Feed not written by application " + appId);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
@GET
@Path("getAllPostsByVRE/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieve all posts for this vre
* @param token a user token associated with a given vre(scope)
* @return
*/
public Response getAllPostsByVRE() {
String scope = ScopeProvider.instance.get();
logger.info("Retrieving all posts coming from vre = " + scope);
List<Feed> feeds = null;
try{
feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByVRE(scope);
Iterator<Feed> it = feeds.iterator();
// remove disabled feeds
while (it.hasNext()) {
Feed f = it.next();
if(f.getType() == FeedType.DISABLED)
it.remove();
}
}catch(Exception e){
logger.error("Unable to retrieve feeds for vre = " + scope, e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
logger.info("List of feeds of vre = " + scope + " retrieved");
return Response.status(Status.OK).entity(feeds).build();
}
@GET
@Path("getAllLikedPostIdsByUser/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Retrieves all liked posts ids relates to token's owner
* @param token
* @return
*/
public Response getAllLikedPostIdsByUser() {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.info("Retrieving all liked feeds IDS for user with id " + username);
List<String> retrievedLikedFeeds = null;
try{
retrievedLikedFeeds = CassandraConnection.getInstance().getDatabookStore().getAllLikedFeedIdsByUser(username);
}catch(Exception e){
logger.error("Unable to read such ids of liked feeds.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
logger.info("Ids of liked feeds by " + username + " retrieved");
return Response.status(Status.OK).entity(retrievedLikedFeeds).build();
}
@GET
@Path("getAllLikedPostsByUser/")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
/**
* Returns all liked feeds of token's owner
* @param limit
* @param token
* @return
*/
public Response getAllLikedPostsByUser(@DefaultValue("10") @QueryParam("limit") int limit) {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.info("Retrieving " + limit + " liked feeds for user with id " + username);
List<Feed> retrievedLikedFeeds = null;
try{
retrievedLikedFeeds = CassandraConnection.getInstance().getDatabookStore().getAllLikedFeedsByUser(username, limit);
}catch(Exception e){
logger.error("Unable to read such liked feeds.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
logger.info("Liked feeds by " + username + " retrieved");
return Response.status(Status.OK).entity(retrievedLikedFeeds).build();
}
}

View File

@ -1,78 +0,0 @@
package org.gcube.portal.social.networking.ws.methods.v1;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.slf4j.LoggerFactory;
/**
* REST interface for the social networking library (tokens).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("/tokens")
@Deprecated
public class Tokens {
private final static String DEFAULT_ROLE = "OrganizationMember";
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Tokens.class);
@POST
@Path("generateApplicationToken/")
@Produces(MediaType.TEXT_PLAIN)
/**
* Allows the owner of the token token to generate a new token for the couple (appId, vre)
* where vre is the same associated to the original user token.
* @param appId
* @param token
* @return
*/
public Response generateApplicationToken(@FormParam("appid") String appId){
logger.info("Incoming request for app token generation. Appid id is " + appId);
//user scope
String userScope = ScopeProvider.instance.get();
// check if an application profile exists for this appId/scope (the discovery of the service will be made on the root)
ApplicationProfile appProfile = SocialUtils.getProfileFromInfrastrucure(appId, userScope);
if(appProfile == null){
logger.error("There is no application profile for this application id and scope!");
return Response.status(Status.FORBIDDEN).entity(ErrorMessages.NO_APP_PROFILE_FOUND).build();
}
logger.info("Generating token for the application with id " + appId);
List<String> roles = new ArrayList<>();
roles.add(DEFAULT_ROLE);
String appToken = null;
try {
// each token is related to an identifier and the context
appToken = authorizationService().generateExternalServiceToken(appId);
} catch (Exception e) {
logger.error("Unable to generate token for app " + appId + " and scope " + userScope);
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.TOKEN_GENERATION_APP_FAILED).build();
}
return Response.status(Status.CREATED).entity(appToken).build();
}
}

View File

@ -1,163 +0,0 @@
package org.gcube.portal.social.networking.ws.methods.v1;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
/**
* REST interface for the social networking library (users).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("/users")
@Deprecated
public class Users {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Users.class);
private static final String NOT_USER_TOKEN_CONTEXT_USED = "User's information can only be retrieved through a user token (not qualified)";
@GET
@Path("readCustomAttr/")
@Produces(MediaType.TEXT_PLAIN)
/**
* A wrapper for the user management library 's readCustomAttr method
* @return Response (OK, BAD REQUEST, ...)
*/
public Response readCustomAttr(
@QueryParam("attribute") String attributeKey
) {
if(attributeKey == null || attributeKey.isEmpty()){
logger.error("Missing/wrong request parameters");
return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.MISSING_PARAMETERS).build();
}
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String toReturn;
if(!TokensUtils.isUserTokenDefault(caller)){
logger.warn(NOT_USER_TOKEN_CONTEXT_USED);
return Response.status(Status.FORBIDDEN).entity("User's information can only be retrieved through a user token").build();
}else{
try{
GCubeUser user = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(username);
toReturn = (String)UserManagerWSBuilder.getInstance().getUserManager().readCustomAttr(user.getUserId(), attributeKey);
}catch(Exception e){
logger.error("Unable to retrieve attribute for user.", e);
return Response.status(Status.NOT_FOUND).build();
}
}
logger.info("Attribute " + attributeKey + " retrieved for user " + username);
return Response.status(Status.OK).entity(toReturn).build();
}
// @PUT
// @Path("updateCustomAttr")
// @Produces(MediaType.TEXT_PLAIN)
// /**
// * A wrapper for the user management library 's saveCustomAttr method
// * @return
// */
// public Response updateCustomAttr(
// @FormParam("attribute") String attributeKey,
// @FormParam("value") String newValue
// ){
//
// if(attributeKey == null || attributeKey.isEmpty() || newValue == null){
//
// logger.error("Missing/wrong request parameters");
// return Response.status(Status.BAD_REQUEST).entity(ErrorMessages.missingParameters).build();
//
// }
//
// Caller caller = AuthorizationProvider.instance.get();
// String username = caller.getClient().getId();
//
// try{
//
// GCubeUser user = userManager.getUserByUsername(username);
// userManager.saveCustomAttr(user.getUserId(), attributeKey, newValue);
//
// }catch(Exception e){
//
// logger.error("Unable to set attribute for user.", e);
// return Response.status(Status.NOT_MODIFIED).build();
//
// }
//
// return Response.status(Status.OK).build();
//
// }
@GET
@Path("getUserFullname")
@Produces(MediaType.TEXT_PLAIN)
/**
* Retrieve user's fullname
* @return
*/
public Response getUserUsername(){
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String toReturn = null;
if(!TokensUtils.isUserTokenDefault(caller)){
logger.warn(NOT_USER_TOKEN_CONTEXT_USED);
return Response.status(Status.FORBIDDEN).entity("User's information can only be retrieved through a user token").build();
}else{
try{
GCubeUser user = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(username);
toReturn = user.getFullname();
logger.info("Found fullname " + toReturn + " for user " + username);
}catch(Exception e){
logger.error("Unable to retrieve attribute for user.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.toString()).build();
}
}
return Response.status(Status.OK).entity(toReturn).build();
}
@GET
@Path("getUserEmail")
@Produces(MediaType.TEXT_PLAIN)
/**
* Retrieve user's email
* @return
*/
public Response getUserEmail(){
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String toReturn = null;
if(!TokensUtils.isUserTokenDefault(caller)){
logger.warn(NOT_USER_TOKEN_CONTEXT_USED);
return Response.status(Status.FORBIDDEN).entity("User's information can only be retrieved through a user token").build();
}else{
try{
GCubeUser user = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(username);
toReturn = user.getEmail();
logger.info("Found email " + toReturn + " for user " + username);
}catch(Exception e){
logger.error("Unable to retrieve attribute for user.", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.toString()).build();
}
}
return Response.status(Status.OK).entity(toReturn).build();
}
}

View File

@ -1,18 +1,17 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
@ -24,37 +23,92 @@ import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.ws.inputs.CommentInputBean;
import org.gcube.portal.social.networking.ws.inputs.PostInputBean;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.Filters;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.gcube.socialnetworking.socialtoken.SocialMessageParser;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.liferay.portlet.journal.FeedIdException;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (comments).
* @author Costantino Perciante at ISTI-CNR
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/comments")
@Api(value=SwaggerConstants.COMMENTS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
/**
* Resource endpoint for Comment (version 2)
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Comments {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Comments.class);
/*
* Retrieve the list of comments belonging to the post id (key) of the token in the related context
* @param key the key as in the POST JSON representation
* @pathExample /get-comments-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583
* @return the list of comments belonging to the post identified by the key in the context identified by the token
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-by-post-id")
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllCommentsByPostId(
@NotNull
@QueryParam("key")
String key) {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
List<Comment> comments = null;
try{
logger.info("Retrieving comments for user id " + username);
comments = CassandraConnection.getInstance().getDatabookStore().getAllCommentByPost(key);
Filters.filterCommentsPerContext(comments, context);
responseBean.setResult(comments);
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such comments.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/*
* Retrieve the list of comments belonging to the owner of the token in the related context
* @return the list of comments belonging to the owner of the token in the related context.
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-user")
@ApiOperation(value = "Retrieve user's comments", response=ResponseBean.class, nickname="get-comments-user", notes="Retrieve the list of comments belonging to the owner of the token in the related context.")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The list of comments is put into the 'result' field", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of comments is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getCommentsUser() {
ResponseBean responseBean = new ResponseBean();
@ -80,24 +134,17 @@ public class Comments {
return Response.status(status).entity(responseBean).build();
}
/*
* Retrieve comments of the token owner in the context bound to the token itself and filter them by date
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-comments-user-by-time")
@ApiOperation(value = "Retrieve user's comments and filter by date", notes="Retrieve comments of the gcube-token's owner in the context bound to the token itself and filter them by date",
response=ResponseBean.class, nickname="get-comments-user-by-time")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The list of comments is put into the 'result' field", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
public Response getCommentsUserByTime(
@QueryParam("time")
@Min(value = 0, message="time cannot be negative")
@ApiParam(
allowableValues="range[0, infinity]",
required=true,
name="time",
value="the base time for filtering operation")
@QueryParam("time")
@Min(value = 0, message="time cannot be negative")
long timeInMillis
) throws ValidationException{
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
@ -122,4 +169,65 @@ public class Comments {
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new comment to a post having as owner the auth token's owner
* @param comment The CommentInputBean object
* @return
* @throws ValidationException
*/
@POST
@Path("comment-post")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successfull created, the new comment is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writeComment(
@NotNull(message="Comment to write is missing")
@Valid
CommentInputBean comment) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.debug("Request of writing a comment coming from user " + username);
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
String postId = comment.getPostid();
String commentText = comment.getText();
String userid = username;
Date time = new Date();
String postOwnerId = CassandraConnection.getInstance().getDatabookStore().readPost(postId).getEntityId();
Comment theComment = SocialUtils.commentPost(userid, time, postId, commentText, postOwnerId, context);
if (theComment != null)
logger.info("Added comment " + theComment.toString());
else {
logger.error("Unable to write comment");
responseBean.setMessage("Unable to write comment, something went wrong please see server log");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(theComment);
responseBean.setSuccess(true);
return Response.status(status).entity(responseBean).build();
} catch(FeedIDNotFoundException ex) {
logger.error("Unable to find a post comment", ex);
responseBean.setMessage("Could not reach the DB to write the comment, something went wrong");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
catch(Exception e) {
logger.error("Unable to write comment", e);
responseBean.setMessage("Could not reach the DB to write the comment, something went wrong");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
}
}

View File

@ -1,12 +1,5 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -35,8 +28,6 @@ import org.gcube.portal.databook.shared.EnhancedFeed;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ElasticSearchConnection;
@ -49,40 +40,47 @@ import org.gcube.vomanagement.usermanagement.model.GCubeGroup;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (post and its comments).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("2/full-text-search")
@Api(value=SwaggerConstants.FULLTEXT, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class FullTextSearch {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(FullTextSearch.class);
/**
* Retrieve posts/comments that match the given query
* @param httpServletRequest
* @param query A string to search for
* @param from the index of the base result to be returned, range[0, infinity], defaults from = 0
* @param quantity defines how many results are most are to be returned, range[1, infinity], defaults from = 0,
* @return The posts/comments returned belong to the context bound to the AUTH Token
* @throws ValidationException
*/
@GET
@Path("search-by-query")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve posts/comments that match the given query",
notes="The posts/comments returned belong to the context bound to the gcube-token",
response=ResponseBean.class, nickname="search-by-query")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of posts/comments that match the query, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts/comments that match the query, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response searchByQuery(
@Context HttpServletRequest httpServletRequest,
@QueryParam("query") @NotNull(message="query cannot be null") @Size(min=1, message="query cannot be empty")
@ApiParam(required=true, defaultValue="none", name="query", value="A string to search for")
String query,
@DefaultValue("0") @QueryParam("from") @Min(value=0, message="from cannot be negative")
@ApiParam(allowableValues="range[0, infinity]",
required=false, name="from", value="the index of the base result to be returned")
int from,
int from,
@DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity cannot be negative")
@ApiParam(allowableValues="range[1, infinity]",
required=false, name="quantity", value="defines how many results are most are to be returned")
int quantity
) throws ValidationException{

View File

@ -1,16 +1,13 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.List;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
@ -19,20 +16,27 @@ import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (hash tags).
* @author Costantino Perciante at ISTI-CNR
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/hashtags")
@Api(value=SwaggerConstants.HASHTAGS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class HashTags {
// Logger
@ -41,11 +45,13 @@ public class HashTags {
@GET
@Path("get-hashtags-and-occurrences/")
@Produces({MediaType.APPLICATION_JSON})
@ApiOperation(value = "Retrieve hashtags", nickname="get-hashtags-and-occurrences",
notes="Retrieve hashtags in the context bound to the gcube-token", response=ResponseBean.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Hashtags and occurrences retrieved, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Hashtags and occurrences retrieved, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
/**
* @return hashtags in the context bound to the auth token
*/
public Response getHashTagsAndOccurrences(){
Caller caller = AuthorizationProvider.instance.get();
@ -75,5 +81,4 @@ public class HashTags {
return Response.status(status).entity(responseBean).build();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import java.util.List;
import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.social.networking.ws.inputs.LikeInputBean;
import org.gcube.portal.social.networking.ws.inputs.PostId;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (likes).
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/likes")
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Likes {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Likes.class);
/*
* Retrieve the list of likes belonging to the post id (key) of the token in the related context
* @param key the key as in the POST JSON representation
* @pathExample /get-likes-by-post-id?key=9ea137e9-6606-45ff-a1a2-94d4e8760583
* @return the list of likes belonging to the post identified by the key in the context identified by the token
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("get-likes-by-post-id")
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of likes is put into the 'result' field"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikesByPostId(
@NotNull
@QueryParam("key")
String key) {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
List<Like> likes = null;
try{
logger.info("Retrieving likes for user id " + username);
likes = CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(key);
responseBean.setResult(likes);
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such likes.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new like to a post in the context of the token
* @param postid The post id to be liked
* @return true if everything is OK
* @throws ValidationException
*/
@POST
@Path("like-post")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successful created, the like operation result is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response like(
@NotNull(message="Post to like is missing")
@Valid
PostId post) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.debug("Request of like coming from user " + username);
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
boolean likeResultOperation = SocialUtils.like(username, post.getPostId(), context);
if (likeResultOperation)
logger.info("Added like OK to postId " + post.getPostId());
else {
logger.error("Unable to like this post"+ post.getPostId());
responseBean.setMessage("Unable to like, something went wrong please see server log");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(true);
responseBean.setSuccess(true);
return Response.status(status).entity(responseBean).build();
}
/**
* Unlike to a post in the context of the token
* @param postid The post id to be liked
* @return true if everything is OK
* @throws ValidationException
*/
@POST
@Path("unlike-post")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "The unlike operation result is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response unlike(
@NotNull(message="Post to unlike is missing")
@Valid
LikeInputBean likeInputBean) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
logger.debug("Request of unlike coming from user " + username);
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
boolean likeResultOperation = SocialUtils.unlike(username, likeInputBean.getLikeid(), likeInputBean.getPostid());
if (likeResultOperation)
logger.info("Unlike OK to postId " + likeInputBean.getPostid());
else {
logger.error("Unable to unlike this post"+ likeInputBean.getPostid());
responseBean.setMessage("Unable to unlike, something went wrong please see server log");
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(true);
responseBean.setSuccess(true);
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -1,12 +1,5 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -16,6 +9,7 @@ import javax.validation.Valid;
import javax.validation.ValidationException;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@ -29,78 +23,106 @@ import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.homelibrary.home.HomeLibrary;
import org.gcube.common.homelibrary.home.workspace.Workspace;
import org.gcube.common.homelibrary.home.workspace.sharing.WorkspaceMessage;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.storagehub.client.plugins.AbstractPlugin;
import org.gcube.common.storagehub.client.proxies.MessageManagerClient;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.portal.notifications.bean.GenericItemBean;
import org.gcube.portal.notifications.thread.MessageNotificationsThread;
import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder;
import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.inputs.MessageInputBean;
import org.gcube.portal.social.networking.ws.inputs.Recipient;
import org.gcube.portal.social.networking.ws.ex.AuthException;
import org.gcube.portal.social.networking.ws.inputs.UserSetNotificationBean;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
import org.gcube.social_networking.socialnetworking.model.beans.MessageInputBean;
import org.gcube.social_networking.socialnetworking.model.beans.Recipient;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* Messages services REST interface
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*/
@Path("2/messages")
@Api(value=SwaggerConstants.MESSAGES, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Messages {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Messages.class);
/**
* Write a message to another user. The sender is the token's owner by default
* @responseExample application/json {"success": true, "message": null, "result": "556142e3-d6f5-4550-b2fa-abe5626625d3"}
* @param input The message to write"
* @param httpServletRequest
* @return see response example
* @throws ValidationException
* @throws UserManagementSystemException
* @throws UserRetrievalFault
*/
@POST
@Path("write-message/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Write a message to another user", notes="Write a message to another user. The sender is the token's owner by default",
response=ResponseBean.class, nickname="write-message")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful write a message. Its id is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful write a message. Its id is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writeMessage(
@NotNull(message="Message to send is missing")
@Valid
@ApiParam(name="input", required=true, allowMultiple=false, value="The message to write")
MessageInputBean input,
@Context HttpServletRequest httpServletRequest) throws ValidationException, UserManagementSystemException, UserRetrievalFault{
logger.debug("Incoming message bean is " + input);
Caller caller = AuthorizationProvider.instance.get();
UserManager um = UserManagerWSBuilder.getInstance().getUserManager();
GCubeUser senderUser = null;
SocialNetworkingUser user = null;
// check if the token belongs to an application token. In this case use J.A.R.V.I.S (the username used to communicate with Liferay)
String senderId = null;
String username = null;
String fullName = "";
logger.debug("Catalogue Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller));
if(!TokensUtils.isUserToken(caller)){
GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser());
SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken());
senderId = jarvis.getUsername();
username = jarvis.getUsername();
fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}else{
senderId = caller.getClient().getId();
}
username = caller.getClient().getId();
senderUser = um.getUserByUsername(username);
fullName = senderUser.getFullname();
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}
String scope = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.CREATED;
String body = input.getBody();
String subject = input.getSubject();
List<Recipient> recipientsIds = input.getRecipients(); // "recipients":[{"recipient":"id recipient"}, ......]
logger.info("Sender is going to be the token's owner [" + senderId + "]");
logger.info("Sender is going to be [" + fullName + "]");
// get the recipients ids (simple check, trim)
List<String> recipientsListFiltered = new ArrayList<String>();
@ -132,27 +154,16 @@ public class Messages {
try{
logger.debug("Trying to send message with body " + body + " subject " + subject + " to users " + recipientsIds + " from " + senderId);
// sender info
GCubeUser senderUser = UserManagerWSBuilder.getInstance().getUserManager().getUserByUsername(senderId);
Workspace workspace = HomeLibrary.getUserWorkspace(senderId);
logger.debug("Workspace is " + workspace.getRoot());
logger.debug("Trying to send message with body " + body + " subject " + subject + " to users " + recipientsIds + " from " + username);
// send message
MessageManagerClient client = AbstractPlugin.messages().build();
logger.debug("Sending message to " + recipientsListFiltered);
String messageId = workspace.getWorkspaceMessageManager()
.sendMessageToPortalLogins(subject, body,
new ArrayList<String>(), recipientsListFiltered);
String messageId = client.sendMessage(recipientsListFiltered, subject, body, input.getAttachmentIds());
// send notification
logger.debug("Message sent to " + recipientsIds + ". Sending message notification to: " + recipientsIds);
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(scope);
SocialNetworkingUser user = new SocialNetworkingUser(
senderUser.getUsername(), senderUser.getEmail(),
senderUser.getFullname(), senderUser.getUserAvatarURL());
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, ScopeProvider.instance.get(), user);
new Thread(new MessageNotificationsThread(recipientsBeans, messageId, subject, body, nm)).start();
responseBean.setSuccess(true);
@ -169,11 +180,14 @@ public class Messages {
@GET
@Path("get-sent-messages")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve the list of sent messages", notes="Retrieve the list of sent messages. The user is the token's owner by default",
response=ResponseBean.class, nickname="get-sent-messages")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful read of the sent messages, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful read of the sent messages, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
/**
*
* @return the list of sent messages of the user (the token's owner)
*/
public Response getSentMessages(){
Caller caller = AuthorizationProvider.instance.get();
@ -184,8 +198,8 @@ public class Messages {
logger.info("Request for retrieving sent messages by " + username);
try{
Workspace workspace = HomeLibrary.getUserWorkspace(username);
List<WorkspaceMessage> sentMessages = workspace.getWorkspaceMessageManager().getSentMessages();
MessageManagerClient client = AbstractPlugin.messages().build();
List<Message> sentMessages = client.getSentMessages();
Collections.reverse(sentMessages);
responseBean.setSuccess(true);
logger.debug("Result is " + sentMessages);
@ -202,11 +216,14 @@ public class Messages {
@GET
@Path("get-received-messages")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve the list of received messages", notes="Retrieve the list of received messages. The user is the token's owner by default",
response=ResponseBean.class, nickname="get-received-messages")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful read of the received messages, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful read of the received messages, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
/**
*
* @return the list of received messages of the user (the token's owner)
*/
public Response getReceivedMessages(){
Caller caller = AuthorizationProvider.instance.get();
@ -216,8 +233,8 @@ public class Messages {
logger.info("Request for retrieving received messages by " + username);
try{
Workspace workspace = HomeLibrary.getUserWorkspace(username);
List<WorkspaceMessage> getMessages = workspace.getWorkspaceMessageManager().getReceivedMessages();
MessageManagerClient client = AbstractPlugin.messages().build();
List<Message> getMessages =client.getReceivedMessages();
Collections.reverse(getMessages);
responseBean.setSuccess(true);
responseBean.setResult(getMessages);
@ -228,6 +245,51 @@ public class Messages {
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Set message read or unread
* @param messageId the message identifier
* @param read true to set read, false to set unread
* @return the result of the operation
* @throws ValidationException
*/
@POST
@Path("set-message-read/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Message set Read or Unread is correctly executed"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response setMessageRead(
@NotNull(message="input is missing")
@FormParam("messageId") String messageId,
@FormParam("read") Boolean read) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
String opExecutor = "";
try{
opExecutor = caller.getClient().getId();
MessageManagerClient client = AbstractPlugin.messages().build();
client.setRead(messageId, read);
String toReturn = "set Message id:" + messageId + (read ? " read" : " unread");
logger.info("set Message id:" + messageId + " read?" + read + " for " + opExecutor);
responseBean.setSuccess(true);
responseBean.setResult(toReturn);
} catch(Exception e){
logger.error("Unable to set message read / unread property for user " + opExecutor, e);
responseBean.setSuccess(false);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -1,14 +1,10 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.ValidationException;
@ -29,54 +25,92 @@ import org.gcube.applicationsupportlayer.social.ApplicationNotificationsManager;
import org.gcube.applicationsupportlayer.social.NotificationsManager;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingSite;
import org.gcube.applicationsupportlayer.social.shared.SocialNetworkingUser;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.portal.databook.shared.Notification;
import org.gcube.portal.databook.shared.NotificationChannelType;
import org.gcube.portal.databook.shared.NotificationType;
import org.gcube.portal.databook.shared.RunningJob;
import org.gcube.portal.notifications.bean.GenericItemBean;
import org.gcube.portal.notifications.thread.JobStatusNotificationThread;
import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder;
import org.gcube.portal.social.networking.caches.UsersCache;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.inputs.JobNotificationBean;
import org.gcube.portal.social.networking.ws.ex.AuthException;
import org.gcube.portal.social.networking.ws.mappers.CatalogueEventTypeMapper;
import org.gcube.portal.social.networking.ws.mappers.JobMapper;
import org.gcube.portal.social.networking.ws.mappers.WorkspaceItemMapper;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
import org.gcube.social_networking.socialnetworking.model.beans.JobNotificationBean;
import org.gcube.social_networking.socialnetworking.model.beans.catalogue.CatalogueEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.AddedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.DeletedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAddedUserEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAdminDowngradeEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderAdminUpgradeEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.FolderRemovedUserEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.RenamedFolderEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.SharedFolderEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.UnsharedFolderEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.UpdatedItemEvent;
import org.gcube.social_networking.socialnetworking.model.beans.workspace.WorkspaceEvent;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.mortbay.log.Log;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (notifications).
* @author Costantino Perciante at ISTI-CNR
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/notifications")
@Api(value=SwaggerConstants.NOTIFICATIONS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Notifications {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Notifications.class);
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
/**
* Retrieve notifications of the token's owner
* @param from must be greater or equal to 1, range[0, infinity]
* @param quantity quantity must be greater or equal to 0
* @return notifications up to quantity
* @throws ValidationException
*/
@GET
@Path("get-range-notifications/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve user's notifications", notes="Retrieve notifications of the gcube-token's owner",
response=ResponseBean.class, nickname="get-range-notifications")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Notifications retrieved and reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Notifications retrieved and reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getRangeNotifications(
@DefaultValue("1") @QueryParam("from") @Min(value=1, message="from must be greater or equal to 1")
@ApiParam(allowableValues="range[0, infinity]",
required=false, allowMultiple=false, value="The base index notification")
@DefaultValue("1") @QueryParam("from") @Min(value=1, message="from must be greater or equal to 1")
int from,
@DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity must be greater or equal to 0")
@ApiParam(allowableValues="range[1, infinity]",
required=false, allowMultiple=false, value="Retrieve notifications up to this quantity")
@DefaultValue("10") @QueryParam("quantity") @Min(value=0, message="quantity must be greater or equal to 0")
int quantity
) throws ValidationException{
) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
@ -102,19 +136,155 @@ public class Notifications {
return Response.status(status).entity(responseBean).build();
}
/**
* Return whether the notifications for this user are enabled or not
* @pathExample /is-user-disabled?username=john.smith
* @responseExample application/json { "success": true, "message": null "result": true }
* @param username the username you want to check
* @return true if the notification for the user are disabled (Catalogue and Workspace ones)
*
*/
@GET
@Path("is-user-disabled/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "true if the notification for the username given as query param are disabled (Catalogue and Workspace ones), false otherwise"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class)
public Response isUserDisabled(
@QueryParam("username") @NotNull(message="username cannot be null")
String username) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
Boolean userDisabled= !isNotificationEnabled(username);
responseBean.setResult(userDisabled);
responseBean.setSuccess(true);
logger.debug("are User " + username + " Notifications Disabled?"+userDisabled);
}catch(Exception e){
logger.error("Unable to read whether the notifications for this user are enabled or not.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
// /**
// * Set user notification enabled or disabled
// * @param disable true if you want to disable the notifications for this user, false if you want to enable them
// * @return the result of the operation
// * @throws ValidationException
// */
// @POST
// @Path("set-user-notifications/")
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// @StatusCodes ({
// @ResponseCode ( code = 200, condition = "Notification set Off or On correctly executed"),
// @ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
// })
// @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=AuthException.class)
// public Response setUserNotifications(
// @NotNull(message="input is missing")
// @Valid
// UserSetNotificationBean setting) throws ValidationException{
//
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// ResponseBean responseBean = new ResponseBean();
// Status status = Status.OK;
//
//
// try{
// String opExecutor = caller.getClient().getId();
// Boolean result = setUserNotificationsOnOff(setting.getUsername(), setting.isDisableNotification(), opExecutor);
// String toReturn = "Could not set notifications";
// if (result) {
// toReturn = "Notifications have been set";
// toReturn += setting.isDisableNotification() ? " OFF (for 29 days unless re-enabled manually) ": " ON ";
// toReturn += "for username=" + setting.getUsername();
// }
// responseBean.setSuccess(true);
// responseBean.setResult(toReturn);
//
// } catch(Exception e){
// logger.error("Unable to set user notification", e);
// responseBean.setSuccess(false);
// responseBean.setMessage(e.getMessage());
// status = Status.INTERNAL_SERVER_ERROR;
// }
//
//
// return Response.status(status).entity(responseBean).build();
// }
/**
* @deprecated
* @param usernameToCheck
* @return true if notification are enabled for this user
* @throws IOException
*/
private boolean isNotificationEnabled(String usernameToCheck) throws IOException {
// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+usernameToCheck;
// Boolean userEnabled = false;
// if(entries.get(key) == null)
// userEnabled = true;
// entries.getConnection().shutdown();
// return userEnabled;
return true;
}
// /**
// *
// * @param username the user you want to disable or enable notifications (max 29 days)
// * @param callerId the username or clientid of the operation executor
// * @param disable true if you want to disable the notifications for this user
// * @return true if the operation was performed
// * @throws IOException
// */
// private Boolean setUserNotificationsOnOff(String username, boolean disable, String callerId) throws IOException {
// MemcachedClient entries = new DistributedCacheClient().getMemcachedClient();
// String key = SocialUtils.DISABLED_USERS_NOTIFICATIONS_NAMESPACE+username;
// OperationFuture<Boolean> result = null;
// if (disable) {
// result = entries.set(key, SocialUtils.CACHING_TIME_TO_EXPIRATION, "op.ex:" + callerId); //operator executor is who silenced the user
// } else {
// result = entries.delete(key);
// }
// try {
// boolean res = result.getStatus().isSuccess();
// entries.getConnection().shutdown();
// return res;
// } catch (Exception e) {
// entries.getConnection().shutdown();
// e.printStackTrace();
// }
// return null;
// }
/**
* Send a JOB notification to a given recipient
* @param job The job bean
* @return
* @throws ValidationException
*/
@POST
@Path("notify-job-status/")
@ApiOperation(value = "Send a JOB Notification", notes="Send a JOB notification to a given recipient",
response=ResponseBean.class, nickname="notify-job-status")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Notification is sent correctly", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Notification is sent correctly"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response notifyJobStatus(
@NotNull(message="input is missing")
@ApiParam(name="job", required=true, allowMultiple=false, value="The job bean")
@Valid JobNotificationBean job) throws ValidationException{
@NotNull(message="input is missing")
@Valid
JobNotificationBean job) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
@ -136,7 +306,9 @@ public class Notifications {
SocialNetworkingUser user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL());
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
new Thread(new JobStatusNotificationThread(job.getRunningJob(), Arrays.asList(recipientBean), nm)).start();
RunningJob theJob = JobMapper.getJob(job);
new Thread(new JobStatusNotificationThread(theJob, Arrays.asList(recipientBean), nm)).start();
responseBean.setSuccess(true);
responseBean.setResult("Notification thread started");
@ -151,4 +323,362 @@ public class Notifications {
return Response.status(status).entity(responseBean).build();
}
/**
* Send a Catalogue notification to a given user
* @param event
* @return
* @throws ValidationException
*/
@POST
@Path("catalogue/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Catalogue Notification is sent correctly"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response catalogue(
@NotNull(message="input is missing")
@Valid
CatalogueEvent event) throws ValidationException, UserManagementSystemException, UserRetrievalFault{
Caller caller = AuthorizationProvider.instance.get();
UserManager um = UserManagerWSBuilder.getInstance().getUserManager();
GCubeUser senderUser = null;
SocialNetworkingUser user = null;
// check if the token belongs to an application token. In this case use J.A.R.V.I.S (the username used to communicate with Liferay)
String username = null;
String fullName = "";
logger.info("Catalogue Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller));
if(!TokensUtils.isUserToken(caller)){
GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser());
SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken());
username = jarvis.getUsername();
fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}else{
username = caller.getClient().getId();
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL());
}
String context = ScopeProvider.instance.get();
logger.info("catalogue notifications from user = " + username);
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
boolean deliveryResult = false;
try {
logger.info("catalogue notifications type is " + event.getType());
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context);
logger.info("social networking site is " + site.getName());
logger.info("context is " + context);
logger.info("user is " + user.getUsername());
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
String[] idsToNotify = event.getIdsToNotify();
if (! event.idsAsGroup()) {
for (int i = 0; i < idsToNotify.length; i++) {
String userIdToNotify = idsToNotify[i];
if (isNotificationEnabled(userIdToNotify)) {
String username2Notify = null;
try {
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
}
catch (Exception e) {
status = Status.BAD_REQUEST;
logger.error("Username not found", e);
responseBean.setSuccess(false);
responseBean.setMessage("Username not found, got: " + userIdToNotify);
return Response.status(status).entity(responseBean).build();
}
logger.info("username2notify " + username2Notify);
logger.info("type is " + CatalogueEventTypeMapper.getType(event.getType()));
logger.info("item id is " + event.getItemId());
logger.info("item text is " + event.getNotifyText());
logger.info("item url is " + event.getItemURL());
deliveryResult =
nm.notifyCatalogueEvent(
CatalogueEventTypeMapper.getType(event.getType()),
username2Notify,
event.getItemId(),
event.getNotifyText(),
event.getItemURL());
}
else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
} else { //the ids are contexts
for (int i = 0; i < idsToNotify.length; i++) {
String contextId = idsToNotify[i];
try {
ScopeBean scope = new ScopeBean(contextId);
if (scope.type() != ScopeBean.Type.VRE) {
logger.error("Context not a VRE");
status = Status.BAD_REQUEST;
responseBean.setSuccess(false);
responseBean.setMessage("Not a VRE Context, only VREs are supported");
return Response.status(status).entity(responseBean).build();
} else { // it is a context and it is a valid VRE
String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members
for (int j = 0; j < userIdsToNotify.length; j++) {
String userIdToNotify = userIdsToNotify[j];
if (isNotificationEnabled(userIdToNotify)) {
deliveryResult =
nm.notifyCatalogueEvent(
CatalogueEventTypeMapper.getType(event.getType()),
userIdToNotify,
event.getItemId(),
event.getNotifyText(),
event.getItemURL());
} else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
}
}
catch(IllegalArgumentException e) {
status = Status.BAD_REQUEST;
logger.error("Context not valid", e);
responseBean.setSuccess(false);
responseBean.setMessage("Context not valid, must start with / " + e.getMessage());
return Response.status(status).entity(responseBean).build();
}
}
}
} catch(Exception e){
logger.error("Unable to send job notification", e);
responseBean.setSuccess(false);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
logger.debug("catalogue notifications should have been sent");
if (deliveryResult) {
responseBean.setSuccess(true);
responseBean.setMessage("catalogue notification delivered correctly");
responseBean.setResult(new Boolean(true));
} else {
responseBean.setSuccess(false);
responseBean.setMessage("An error occurred between this service and Cassandra DB, notification not delivered correctly");
responseBean.setResult(new Boolean(false));
}
return Response.status(status).entity(responseBean).build();
}
/**
* Send a Workspace notification to a given user
* @param event
* @return
* @throws ValidationException
*/
@POST
@Path("workspace/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Workspace Notification is sent correctly"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response workspace(
@NotNull(message="input is missing")
@Valid
WorkspaceEvent event) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
logger.debug("workspace notifications from = " + username);
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
boolean deliveryResult = false;
try {
GCubeUser senderUser = null;
SocialNetworkingUser user = null;
String fullName = "";
logger.debug("workspace notifications type is " + event.getType());
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(context);
UserManager um = UserManagerWSBuilder.getInstance().getUserManager();
logger.debug("Workspace Notification called by " + caller.getClient().getId() + " isUser?"+TokensUtils.isUserToken(caller));
if(!TokensUtils.isUserToken(caller)){
GCubeUser jarvis = UserManagerWSBuilder.getInstance().getUserManager().getUserByEmail(LiferayJSONWsCredentials.getSingleton().getUser());
SecurityTokenProvider.instance.set(LiferayJSONWsCredentials.getSingleton().getNotifierUserToken());
username = jarvis.getUsername();
fullName = caller.getClient().getId().replace("service-account-", ""); // the actual name of the IAM Client
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), fullName, senderUser.getUserAvatarURL());
}else{
username = caller.getClient().getId();
senderUser = um.getUserByUsername(username);
user = new SocialNetworkingUser(senderUser.getUsername(), senderUser.getEmail(), senderUser.getFullname(), senderUser.getUserAvatarURL());
}
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, user);
String[] idsToNotify = event.getIdsToNotify();
if (! event.idsAsGroup()) {
for (int i = 0; i < idsToNotify.length; i++) {
String userIdToNotify = idsToNotify[i];
if (isNotificationEnabled(userIdToNotify)) {
String username2Notify = "";
try {
username2Notify = um.getUserByUsername(userIdToNotify).getUsername();
}
catch (Exception e) {
status = Status.NOT_ACCEPTABLE;
logger.error("Username not found", e);
responseBean.setSuccess(false);
responseBean.setMessage("Username not found, received: " + userIdToNotify);
return Response.status(status).entity(responseBean).build();
}
deliveryResult = notifyWorkspaceEvent(event, nm, username2Notify);
}
else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
} else { //the ids are contexts
for (int i = 0; i < idsToNotify.length; i++) {
String contextId = idsToNotify[i];
try {
ScopeBean scope = new ScopeBean(contextId);
if (scope.type() != ScopeBean.Type.VRE) {
logger.error("Context not a VRE");
status = Status.BAD_REQUEST;
responseBean.setSuccess(false);
responseBean.setMessage("Not a VRE Context, only VREs are supported");
return Response.status(status).entity(responseBean).build();
} else { // it is a context and it is a valid VRE
String[] userIdsToNotify = getUsernamesByContext(scope).toArray(new String[0]); //resolve the members
for (int j = 0; j < userIdsToNotify.length; j++) {
String userIdToNotify = userIdsToNotify[j];
if (isNotificationEnabled(userIdToNotify))
deliveryResult = notifyWorkspaceEvent(event, nm, userIdToNotify);
else {
Log.info("Notification disabled (admin) for user "+userIdToNotify + " will not notify");
}
}
}
}
catch(IllegalArgumentException e) {
status = Status.BAD_REQUEST;
logger.error("Context not valid", e);
responseBean.setSuccess(false);
responseBean.setMessage("Context not valid, must start with / " + e.getMessage());
return Response.status(status).entity(responseBean).build();
}
}
}
} catch(Exception e){
logger.error("Unable to send job notification", e);
responseBean.setSuccess(false);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
logger.debug("workspace notifications should have been sent");
if (deliveryResult) {
responseBean.setSuccess(true);
responseBean.setMessage("Workspace notification delivered correctly");
responseBean.setResult(new Boolean(true));
} else {
responseBean.setSuccess(false);
responseBean.setMessage("An error occurred between this service and Cassandra DB, notification not delivered correctly");
responseBean.setResult(new Boolean(false));
}
return Response.status(status).entity(responseBean).build();
}
/**
*
* @param event
* @param nm
* @param idToNotify
* @return
*/
private boolean notifyWorkspaceEvent(WorkspaceEvent event, NotificationsManager nm, String idToNotify) {
try {
switch (event.getType()) {
case ITEM_NEW: {
AddedItemEvent itemBean = (AddedItemEvent) event;
return nm.notifyAddedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_UPDATE: {
UpdatedItemEvent itemBean = (UpdatedItemEvent) event;
return nm.notifyUpdatedItem(idToNotify, WorkspaceItemMapper.getFileItem(itemBean.getItem()), WorkspaceItemMapper.getSharedFolder(itemBean.getItem().getParent()));
}
case ITEM_DELETE: {
DeletedItemEvent itemBean = (DeletedItemEvent) event;
return nm.notifyRemovedItem(idToNotify, itemBean.getItemName(), WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_SHARE: {
SharedFolderEvent itemBean = (SharedFolderEvent) event;
return nm.notifyFolderSharing(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_UNSHARE: {
UnsharedFolderEvent itemBean = (UnsharedFolderEvent) event;
return nm.notifyFolderUnsharing(idToNotify, itemBean.getUnsharedFolderId(), itemBean.getUnsharedFolderName());
}
case FOLDER_RENAME: {
RenamedFolderEvent itemBean = (RenamedFolderEvent) event;
return nm.notifyFolderRenaming(idToNotify, itemBean.getPreviousName(), itemBean.getNewName(), itemBean.getRenamedFolderId());
}
case FOLDER_ADMIN_UPGRADE: {
FolderAdminUpgradeEvent itemBean = (FolderAdminUpgradeEvent) event;
return nm.notifyAdministratorUpgrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADMIN_DOWNGRADE: {
FolderAdminDowngradeEvent itemBean = (FolderAdminDowngradeEvent) event;
return nm.notifyAdministratorDowngrade(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
case FOLDER_ADDEDUSER: {
FolderAddedUserEvent itemBean = (FolderAddedUserEvent) event;
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
return nm.notifyFolderAddedUsers(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()), itemBean.getNewAddedUserIds(), userManager);
}
case FOLDER_REMOVEDUSER: {
FolderRemovedUserEvent itemBean = (FolderRemovedUserEvent) event;
return nm.notifyFolderRemovedUser(idToNotify, WorkspaceItemMapper.getSharedFolder(itemBean.getFolder()));
}
default:
break;
}
} catch(Exception e){
logger.error("Unable to send job notification", e);
return false;
}
return false;
}
/**
*
* @param context
* @return
* @throws Exception
*/
private List<String> getUsernamesByContext(ScopeBean context) throws Exception {
List<String> usernames = new ArrayList<String>();
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
long groupId = groupManager.getGroupIdFromInfrastructureScope(context.toString());
// first retrieve ids
List<Long> userIds = userManager.getUserIdsByGroup(groupId);
// check info in cache when available
UsersCache cache = UsersCache.getSingleton();
for (Long userId : userIds) {
if(cache.getUser(userId) == null){
GCubeUser theUser = userManager.getUserById(userId);
if(theUser != null){
usernames.add(theUser.getUsername());
cache.pushEntry(userId, theUser);
}
}else
usernames.add(cache.getUser(userId).getUsername());
}
return usernames;
}
}

View File

@ -1,11 +1,5 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -24,8 +18,6 @@ import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
@ -36,25 +28,35 @@ import org.gcube.vomanagement.usermanagement.model.GCubeRole;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (people). Used by OAUTH 2.0 apps/users.
* @author Costantino Perciante at ISTI-CNR
* REST interface for the social service (people). Used by OAUTH 2.0 apps/users.
*/
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
@Path("2/people")
@Api(value=SwaggerConstants.PEOPLE, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
public class People {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(People.class);
/**
* @responseExample application/json { "success" : true, "message" : null, "result" : { "roles" : [ ], "context" : "***", "avatar" : "https://*****3D", "fullname" : "John Smith", "username" : "john.smith" } }
* @return the user's profile. The user in this case is the one bound to the token
*/
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("profile")
@ApiOperation(value = "Retrieve user's profile", notes="Retrieve the user's profile. The user in this case is the one bound to the token which can be of any kind (qualified, default)",
response=ResponseBean.class, nickname="profile")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of user's profile, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of user's profile, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getProfile(){
Caller caller = AuthorizationProvider.instance.get();
@ -80,6 +82,7 @@ public class People {
toReturn.put("username", user.getUsername());
toReturn.put("avatar", user.getUserAvatarURL());
toReturn.put("fullname", user.getFullname());
toReturn.put("context", scope);
List<GCubeRole> roles = roleManager.listRolesByUserAndGroup(user.getUserId(), groupManager.getGroupIdFromInfrastructureScope(scope));
List<String> rolesNames = new ArrayList<String>();
for (GCubeRole gCubeRole : roles) {

View File

@ -1,15 +1,9 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import javax.validation.ValidationException;
@ -25,15 +19,17 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.portal.databook.shared.PostWithAttachment;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.databook.shared.*;
import org.gcube.portal.databook.shared.ex.ColumnNameNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.databook.shared.ex.FeedTypeNotFoundException;
import org.gcube.portal.databook.shared.ex.PrivacyLevelTypeNotFoundException;
import org.gcube.portal.social.networking.ws.inputs.PostInputBean;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.CassandraConnection;
@ -42,50 +38,61 @@ import org.gcube.portal.social.networking.ws.utils.Filters;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (feeds).
* @author Costantino Perciante at ISTI-CNR
* REST interface for the social networking library (posts).
* @author Ahmed Ibrahim ISTI-CNR
*/
@Path("2/posts")
@Api(value=SwaggerConstants.POSTS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Posts {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Posts.class);
/**
* Retrieve posts of the auth token's owner, and allow to filter them by time"
* @param timeInMillis The reference time since when retrieving posts
* @return the posts
* @throws ValidationException
*/
@GET
@Path("get-posts-user-since/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve user's posts", notes="Retrieve posts of the gcube-token's owner, and allow to filter them by time",
response=ResponseBean.class, nickname="get-posts-user-since")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of posts, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getRecentPostsByUserAndDate(
@QueryParam("time") @Min(value = 0, message="time cannot be negative")
@ApiParam(allowableValues="range[0, infinity]", name="time",
required=true, allowMultiple=false, value="The reference time since when retrieving posts")
@QueryParam("time") @Min(value = 0, message="time cannot be negative")
long timeInMillis
) throws ValidationException{
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
String username = caller.getClient().getId();
List<Feed> feeds = null;
List<Post> posts = null;
try{
logger.info("Retrieving feeds for user id " + username + " and reference time " + timeInMillis);
feeds = CassandraConnection.getInstance().getDatabookStore().getRecentFeedsByUserAndDate(username, timeInMillis);
Filters.filterFeedsPerContext(feeds, context);
Filters.hideSensitiveInformation(feeds, caller.getClient().getId());
responseBean.setResult(feeds);
logger.info("Retrieving post for user id " + username + " and reference time " + timeInMillis);
posts = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByUserAndDate(username, timeInMillis);
Filters.filterPostsPerContext(posts, context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
responseBean.setResult(posts);
responseBean.setMessage("");
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
logger.error("Unable to retrieve such posts.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
@ -94,14 +101,18 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve all user's posts
* @return all posts of the auth token's owner in the context identified by the token
*/
@GET
@Path("get-posts-user/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve all user's posts", notes="Retrieve all posts of the gcube-token's owner",
response=ResponseBean.class, nickname="get-posts-user")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of posts, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByUser() {
Caller caller = AuthorizationProvider.instance.get();
@ -109,13 +120,13 @@ public class Posts {
String context = ScopeProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
List<Feed> feeds = null;
List<Post> posts = null;
try{
logger.debug("Retrieving feeds for user with id " + username);
feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByUser(username);
Filters.filterFeedsPerContext(feeds, context);
Filters.hideSensitiveInformation(feeds, caller.getClient().getId());
responseBean.setResult(feeds);
logger.debug("Retrieving posts for user with id " + username);
posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByUser(username);
Filters.filterPostsPerContext(posts, context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
responseBean.setResult(posts);
responseBean.setMessage("");
responseBean.setSuccess(true);
}catch(Exception e){
@ -128,20 +139,71 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve a post by id
* @return the post if the post id belongs to a post in the context identified by the token
*/
@GET
@Path("get-post/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getPost(@QueryParam("id") String id) {
String context = ScopeProvider.instance.get();
Caller caller = AuthorizationProvider.instance.get();
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
List<Post> posts = new ArrayList<>();
try{
logger.debug("Retrieving post with id " + id);
try {
posts.add(CassandraConnection.getInstance().getDatabookStore().readPost(id));
} catch(FeedIDNotFoundException e){
responseBean.setMessage("The post with id " + id + " does not exist in context " + context);
responseBean.setSuccess(false);
return Response.status(status).entity(responseBean).build();
}
Filters.filterPostsPerContext(posts, context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
if (posts.isEmpty()) {
responseBean.setMessage("The post with id " + id + " does not belong to this context " + context);
responseBean.setSuccess(false);
status = Status.FORBIDDEN;
return Response.status(status).entity(responseBean).build();
}
responseBean.setResult(posts.get(0));
responseBean.setMessage("");
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such post.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve a given quantity of latest user's posts
* @param quantity the number of latest post to get
* @pathExample /get-posts-user-quantity?quantity=10
* @return all posts of the auth token's owner in the context identified by the token, in reverse chronological order up to quantity (at most)
* @throws ValidationException
*/
@GET
@Path("get-posts-user-quantity/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve a given quantity of latest user's posts", notes="Retrieve a given quantity of latest posts of the gcube-token's owner",
response=ResponseBean.class, nickname="get-posts-user-quantity")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful retrieval of posts, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful retrieval of posts, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getQuantityPostsByUser(
@DefaultValue("10")
@QueryParam("quantity")
@Min(value=0, message="quantity cannot be negative")
@ApiParam(allowableValues="range[0, infinity]", name="quantity",
required=false, allowMultiple=false, value="How many posts needs to be retrieved at most")
@DefaultValue("10")
@QueryParam("quantity")
@Min(value=0, message="quantity cannot be negative")
int quantity) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
@ -150,7 +212,7 @@ public class Posts {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
List<Feed> feeds = new ArrayList<Feed>();
List<Post> posts = new ArrayList<>();
// if quantity is zero, just return an empty list
if(quantity == 0){
@ -158,15 +220,19 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
try{
logger.debug("Retrieving last " + quantity + " feeds made by user " + username);
feeds = CassandraConnection.getInstance().getDatabookStore().getRecentFeedsByUser(username, -1);
Filters.filterFeedsPerContext(feeds, context);
feeds = feeds.subList(0, quantity);
Filters.hideSensitiveInformation(feeds, caller.getClient().getId());
responseBean.setResult(feeds);
logger.debug("getRecentPostsByUser first, posts made by user " + username);
posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByUser(username);
if (posts != null)
logger.debug("got " + posts.size() + " posts");
logger.debug("Retrieving last " + quantity + " posts made by user " + username + " in context = "+context);
Filters.filterPostsPerContext(posts, context);
quantity = (quantity > posts.size()) ? posts.size() : quantity;
posts = posts.subList(0, quantity);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
responseBean.setResult(posts);
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve such feeds.", e);
logger.error("Unable to retrieve such posts.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
@ -174,20 +240,23 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new user post having as owner the auth token's owner
* @param post The post to be written
* @return
* @throws ValidationException
*/
@POST
@Path("write-post-user")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create a new user post", notes="Create a new user post having as owner the gcube-token's owner",
response=ResponseBean.class, nickname="write-post-user")
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Successfull created, the new post is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writePostUser(
@NotNull(message="Post to write is missing")
@Valid
@ApiParam(name="post",
required=true, allowMultiple=false, value="The post to be written")
@NotNull(message="Post to write is missing")
@Valid
PostInputBean post) throws ValidationException{
logger.debug("Request of writing a feed coming from user " + post);
@ -214,18 +283,18 @@ public class Posts {
// try to share
logger.debug("Trying to share user feed...");
Feed res = SocialUtils.shareUserUpdate(
logger.debug("Trying to share user post...");
Post res = SocialUtils.shareUserUpdate(
username,
postText,
context,
postText,
context,
previewTitle,
previewDescription,
previewHost,
previewUrl,
httpImageUrl,
httpImageUrl,
enableNotification
);
);
if(res != null){
logger.debug("Post correctly written by user " + username);
@ -243,15 +312,18 @@ public class Posts {
}
/**
* Retrieve the application's posts
* @return the application (IAM Client) posts belonging to the token's owner (i.e., an application)"
*/
@GET
@Path("get-posts-app/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve the application's posts", notes="Retrieve the application's posts belonging to the gcube-token's owner (i.e., an application)",
response=ResponseBean.class, nickname="get-posts-app")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfull retrieved posts, they are reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 403, message = "There is no application profile with such token", response=ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByApp() {
Caller caller = AuthorizationProvider.instance.get();
@ -273,9 +345,9 @@ public class Posts {
}
try{
logger.debug("Retrieving feeds for app with id " + appId);
List<Feed> feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByApp(appId);
Filters.filterFeedsPerContext(feeds, context);
logger.debug("Retrieving posts for app with id " + appId);
List<Post> feeds = CassandraConnection.getInstance().getDatabookStore().getAllPostsByApp(appId);
Filters.filterPostsPerContext(feeds, context);
responseBean.setSuccess(true);
responseBean.setResult(feeds);
@ -291,21 +363,23 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Create a new application post having as owner-application the token's owner (the IAM Client), note that the application must be registered on the Information System
* @param post The post to be written
* @return
*/
@POST
@Path("write-post-app")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Create a new application post", notes="Create a new application post having as owner-application the gcube-token's owner",
response=ResponseBean.class, nickname="write-post-app")
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Successfull created, the new post is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 403, message = "There is no application profile with such token", response=ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull created, the new post is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "\"There is no application profile with such token"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response writePostApp(
@NotNull(message="Post to write is null")
@Valid
@ApiParam(name="post",
required=true, allowMultiple=false, value="The post to be written")
@NotNull(message="Post to write is null")
@Valid
PostInputBean post){
Caller caller = AuthorizationProvider.instance.get();
@ -328,7 +402,7 @@ public class Posts {
}
// parse
String feedText = post.getText();
String postText = post.getText();
String previewTitle = post.getPreviewtitle();
String previewDescription = post.getPreviewdescription();
String httpImageUrl = post.getHttpimageurl();
@ -341,17 +415,17 @@ public class Posts {
else
logger.debug("Disable notification for this application post.");
// write feed + notification if it is the case
Feed written = SocialUtils.shareApplicationUpdate(
feedText,
params,
previewTitle,
previewDescription,
httpImageUrl,
appProfile,
// write post + notification if it is the case
Post written = SocialUtils.shareApplicationUpdate(
postText,
params,
previewTitle,
previewDescription,
httpImageUrl,
appProfile,
caller,
enableNotification
);
);
if(written != null){
responseBean.setResult(written);
@ -366,28 +440,31 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
*
* @return all the posts in the context bound to the auth token
*/
@GET
@Path("get-posts-vre/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve vre's posts", notes="Retrieve all the posts in the context bound to the gcube-token",
response=ResponseBean.class, nickname="get-posts-vre")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfull retrieved posts, they are reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllPostsByVRE() {
String scope = ScopeProvider.instance.get();
String context = ScopeProvider.instance.get();
Caller caller = AuthorizationProvider.instance.get();
logger.debug("Retrieving all posts coming from vre = " + scope);
logger.debug("Retrieving all posts coming from vre = " + context);
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
List<Feed> feeds = CassandraConnection.getInstance().getDatabookStore().getAllFeedsByVRE(scope);
Filters.hideSensitiveInformation(feeds, caller.getClient().getId());
responseBean.setResult(feeds);
List<Post> posts = CassandraConnection.getInstance().getDatabookStore().getAllPostsByVRE(context);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
responseBean.setResult(posts);
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve feeds for vre = " + scope, e);
logger.error("Unable to retrieve posts for vre = " + context, e);
status = Status.INTERNAL_SERVER_ERROR;
responseBean.setMessage(e.toString());
responseBean.setSuccess(false);
@ -396,19 +473,70 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* return the most recent posts for this vre up to quantity param and the last index of the posts in the timeline
* lastReturnedPostTimelineIndex is useful to know from where to start the range the next time you ask, because there are deletions
*
* @param from the range start (most recent feeds for this vre) has to be greater than 0
* @param quantity the number of most recent feeds for this vre starting from "from" param
* @pathExample /get-recent-posts-vre-by-range?from=1&quantity=10
* @return a <class>RangePosts</class> containing of most recent feeds for this vre
* @throws FeedTypeNotFoundException
* @throws PrivacyLevelTypeNotFoundException
* @throws ColumnNameNotFoundException
*/
@GET
@Path("get-recent-posts-vre-by-range/")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getRecentPostsByVREAndRange(
@QueryParam("from")
@Min(value=1, message="from cannot be negative")
int from,
@QueryParam("quantity")
@Min(value=1, message="quantity cannot be negative")
int quantity) throws ValidationException {
String context = ScopeProvider.instance.get();
Caller caller = AuthorizationProvider.instance.get();
logger.debug("Retrieving all posts coming from vre = " + context);
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
RangePosts rangePosts = CassandraConnection.getInstance().getDatabookStore().getRecentPostsByVREAndRange(context, from, quantity);
Filters.hideSensitiveInformation(rangePosts.getPosts(), caller.getClient().getId());
responseBean.setResult(rangePosts);
responseBean.setSuccess(true);
}catch(Exception e){
logger.error("Unable to retrieve posts for vre = " + context, e);
status = Status.INTERNAL_SERVER_ERROR;
responseBean.setMessage(e.toString());
responseBean.setSuccess(false);
}
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve posts containing the hashtag in the context bound to the auth token
* @param hashtag he hashtag to be contained within the posts
* @pathExample /get-posts-by-hashtag?hashtag=#thehashtag
* @return the posts in the context bound to the auth token matching the hashtag
* @throws ValidationException
*/
@GET
@Path("get-posts-by-hashtag/")
@Produces({MediaType.APPLICATION_JSON})
@ApiOperation(value = "Retrieve posts containing the hashtag", notes="Retrieve posts containing the hashtag in the context bound to the gcube-token",
response=ResponseBean.class, nickname="get-posts-by-hashtag")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfull retrieved posts, they are reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getPostsByHashTags(
@QueryParam("hashtag")
@NotNull(message="hashtag cannot be missing")
@ApiParam(name="hashtag",
required=true, allowMultiple=false, value="The hashtag to be contained within the posts")
@QueryParam("hashtag")
@NotNull(message="hashtag cannot be missing")
String hashtag) throws ValidationException {
Caller caller = AuthorizationProvider.instance.get();
@ -419,9 +547,9 @@ public class Posts {
logger.info("User " + username + " has requested posts containing hashtag " + hashtag + " in context " + context);
try{
DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore();
List<Feed> feeds = datastore.getVREFeedsByHashtag(context, hashtag);
Filters.hideSensitiveInformation(feeds, caller.getClient().getId());
responseBean.setResult(feeds);
List<Post> posts = datastore.getVREPostsByHashtag(context, hashtag);
Filters.hideSensitiveInformation(posts, caller.getClient().getId());
responseBean.setResult(posts);
responseBean.setSuccess(true);
}catch(Exception e){
@ -431,34 +559,37 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve ids (UUID) of the liked posts by the user
* @return ids (UUID) of the liked posts by the user in the context bound to the auth token
*/
@GET
@Path("get-id-liked-posts/")
@Produces({MediaType.APPLICATION_JSON})
@ApiOperation(value = "Retrieve ids (UUID) of the liked by the user", notes="Retrieve ids (UUID) of the liked by the user in the context bound to the gcube-token",
response=ResponseBean.class, nickname="get-id-liked-posts")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfull retrieved ids, they are reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Sccessfull retrieved ids, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikedPostIdsByUser() {
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
logger.debug("Retrieving all liked feeds for user with id " + username + " in context " + context);
logger.debug("Retrieving all liked posts for user with id " + username + " in context " + context);
List<String> retrievedLikedFeedsIds = null;
List<String> retrievedLikedPostsIds = null;
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
DatabookStore datastore = CassandraConnection.getInstance().getDatabookStore();
retrievedLikedFeedsIds = datastore.getAllLikedFeedIdsByUser(username);
Filters.filterFeedsPerContextById(retrievedLikedFeedsIds, context);
responseBean.setResult(retrievedLikedFeedsIds);
retrievedLikedPostsIds = datastore.getAllLikedPostIdsByUser(username);
Filters.filterFeedsPerContextById(retrievedLikedPostsIds, context);
responseBean.setResult(retrievedLikedPostsIds);
responseBean.setSuccess(true);
logger.debug("Ids of liked feeds by " + username + " retrieved");
logger.debug("Ids of liked posts by " + username + " retrieved");
}catch(Exception e){
logger.error("Unable to read such ids of liked feeds.", e);
logger.error("Unable to read such ids of liked Posts.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
@ -467,43 +598,105 @@ public class Posts {
return Response.status(status).entity(responseBean).build();
}
/**
* Retrieve posts liked by the user
* @param limit The maximum number of posts to be retrieved
* @return posts liked by the user (up to a given quantity) in the context bound to the auth token
* @throws ValidationException
*/
@GET
@Path("get-liked-posts/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Retrieve posts liked by the user", notes="Retrieve posts liked by the user (up to a given quantity) in the context bound to the gcube-token",
response=ResponseBean.class, nickname="get-liked-posts")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successfull retrieved posts. They are reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successfull retrieved posts, they are reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllLikedPostsByUser(
@DefaultValue("10")
@QueryParam("limit")
@Min(message="limit cannot be negative", value = 0)
@ApiParam(name="limit",
required=false, allowMultiple=false, value="The maximum number of posts to be retrieved")
@DefaultValue("10")
@QueryParam("limit")
@Min(message="limit cannot be negative", value = 0)
int limit) throws ValidationException{
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
List<Feed> retrievedLikedFeeds = null;
List<Post> retrievedLikedPosts = null;
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
logger.debug("Retrieving " + limit + " liked feeds for user with id " + username + " in context " + context);
retrievedLikedFeeds = CassandraConnection.getInstance().getDatabookStore().getAllLikedFeedsByUser(username, limit);
Filters.filterFeedsPerContext(retrievedLikedFeeds, context);
Filters.hideSensitiveInformation(retrievedLikedFeeds, caller.getClient().getId());
responseBean.setResult(retrievedLikedFeeds);
logger.debug("Retrieving " + limit + " liked posts for user with id " + username + " in context " + context);
retrievedLikedPosts = CassandraConnection.getInstance().getDatabookStore().getAllLikedPostsByUser(username, limit);
Filters.filterPostsPerContext(retrievedLikedPosts, context);
Filters.hideSensitiveInformation(retrievedLikedPosts, caller.getClient().getId());
responseBean.setResult(retrievedLikedPosts);
responseBean.setSuccess(true);
logger.debug("Liked feeds by " + username + " retrieved");
logger.debug("Liked posts by " + username + " retrieved");
}catch(Exception e){
logger.error("Unable to read such liked feeds.", e);
logger.error("Unable to read such liked posts.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
//libapi
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("save-user-post-attachments-lib")
public Response saveUserPostLib(
@NotNull(message="post to add is missing")
@Valid
PostWithAttachment postWithAttachment
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
Post post = postWithAttachment.getPost();
logger.info("Post is " + post);
List<Attachment> attachments = postWithAttachment.getAttachments();
logger.info("Attachments are " + attachments);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(post,attachments);
responseBean.setResult(result);
responseBean.setMessage("");
responseBean.setSuccess(result);
}catch(Exception e){
logger.error("Unable to write comment.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("save-app-post-attachments-lib")
public Response saveAppPostLib(
@NotNull(message="post to add is missing")
@Valid
PostWithAttachment postWithAttachment
) throws ValidationException{
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try{
Post post = postWithAttachment.getPost();
List<Attachment> attachments = postWithAttachment.getAttachments();
boolean result = CassandraConnection.getInstance().getDatabookStore().saveAppPost(post,attachments);
responseBean.setResult(result);
responseBean.setMessage("");
responseBean.setSuccess(result);
}catch(Exception e){
logger.error("Unable to write comment.", e);
responseBean.setMessage(e.getMessage());
responseBean.setSuccess(false);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -1,12 +1,6 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import static org.gcube.common.authorization.client.Constants.authorizationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import javax.validation.Valid;
import javax.validation.ValidationException;
@ -21,21 +15,21 @@ import javax.ws.rs.core.Response.Status;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.inputs.ApplicationId;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.SocialUtils;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (tokens).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("2/tokens")
@Api(value=SwaggerConstants.TOKENS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@Deprecated
public class Tokens {
// Logger
@ -45,16 +39,20 @@ public class Tokens {
@Path("generate-application-token/")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Generate an application token", notes="Generate an application token for the application with id app_id",
response=ResponseBean.class, nickname="generate-application-token")
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Successful creation of the token, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 403, message = "There is no application profile with such id", response=ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 201, condition = "Successful creation of the token, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 403, condition = "There is no application profile with such id"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
/**
* Generate a legacy application auth token for the application with id app_id
* @param input The bean containing the app_id field
* @return the legacy application token
* @throws ValidationException
*/
public Response generateApplicationToken(
@NotNull(message="Missing input parameter")
@Valid
@ApiParam(name="input", required=true, allowMultiple=false, value="The bean containing the app_id field")
ApplicationId input) throws ValidationException{
logger.debug("Incoming request for app token generation.");

View File

@ -24,10 +24,9 @@ import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.portal.social.networking.caches.UsersCache;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.KeycloakAPICredentials;
import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.ErrorMessages;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
@ -37,21 +36,26 @@ import org.gcube.vomanagement.usermanagement.RoleManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeRole;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Authorization;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
/**
* REST interface for the social networking library (users).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("2/users")
@Api(value=SwaggerConstants.USERS, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class Users {
// Logger
@ -59,19 +63,23 @@ public class Users {
private static final String NOT_USER_TOKEN_CONTEXT_USED = "User's information can only be retrieved through a user token (not qualified)";
private static final List<String> GLOBAL_ROLES_ALLOWED_BY_LOCAL_CALL_METHOD = Arrays.asList("DataMiner-Manager","Quota-Manager");
/**
* Read a user's custom attribute. The user is the one owning the token
* @param attributeKey The key of the attribute to be read
* @return the user's custom attribute
* @throws ValidationException
*/
@GET
@Path("get-custom-attribute/")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Read a user's custom attribute", notes="Read a user's custom attribute. The user is the one owning the token",
response=ResponseBean.class, nickname="get-custom-attribute")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Successful read of the attribute, reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 404, message = "Such an attribute doesn't exist", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "Successful read of the attribute, reported in the 'result' field of the returned object"),
@ResponseCode ( code = 404, condition = "Such an attribute doesn't exist"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response readCustomAttr(
@QueryParam("attribute")
@NotNull(message="attribute name is missing")
@ApiParam(name="attribute", required=true, allowMultiple=false, value="The key of the attribute to be read")
String attributeKey
) throws ValidationException {
@ -104,69 +112,17 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
// @PUT
// @Path("update-custom-attribute")
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// @ApiOperation(value = "Update a user's custom attribute", notes="Update a user's custom attribute. The user is the one owning the token",
// response=ResponseBean.class, nickname="update-custom-attribute")
// @ApiResponses(value = {
// @ApiResponse(code = 200, message = "Successful update of the attribute, the new value is reported in the 'result' field of the returned object", response = ResponseBean.class),
// @ApiResponse(code = 400, message = "Key or value for the new attribute missing", response=ResponseBean.class),
// @ApiResponse(code = 500, message = ErrorMessages.errorMessageApiResult, response=ResponseBean.class),
// @ApiResponse(code = 304, message = "Attribute not modified", response=ResponseBean.class)})
// public Response updateCustomAttr(
// @NotNull(message="input is missing")
// @ApiParam(name="input", required=true, allowMultiple=false, value="The object having an attribute key and a value key for the new value")
// String inputJsonObj
// ) throws ValidationException{
//
// Caller caller = AuthorizationProvider.instance.get();
// String username = caller.getClient().getId();
// ResponseBean responseBean = new ResponseBean();
// Status status = Status.OK;
//
// try{
//
// // Jackson parser
// ObjectMapper mapper = new ObjectMapper();
// JsonNode actualObj = mapper.readTree(inputJsonObj);
// String attributeKey = actualObj.get("attribute").asText();
// String newValue = actualObj.get("value").asText();
//
// if(attributeKey == null || attributeKey.isEmpty() || newValue == null){
//
// logger.error("Missing/wrong request parameters");
// status = Status.BAD_REQUEST;
// responseBean.setMessage(ErrorMessages.missingParameters);
// return Response.status(status).entity(responseBean).build();
//
// }
//
// GCubeUser user = userManager.getUserByUsername(username);
// userManager.saveCustomAttr(user.getUserId(), attributeKey, newValue);
// responseBean.setSuccess(true);
// responseBean.setResult(newValue);
//
// }catch(Exception e){
//
// logger.error("Unable to set attribute for user.", e);
// status = Status.NOT_MODIFIED;
// responseBean.setMessage(e.toString());
//
// }
//
// return Response.status(status).entity(responseBean).build();
// }
/**
* Read the user's fullname. The user is the one owning the token
* @return the user's fullname
*/
@GET
@Path("get-fullname")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Read the user's fullname", notes="Read the user's fullname. The user is the one owning the token",
response=ResponseBean.class, nickname="get-fullname")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The user's fullname is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The user's fullname is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserFullname(){
Caller caller = AuthorizationProvider.instance.get();
@ -199,14 +155,17 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* Read the user's email address. The user is the one owning the token
* @return rhe user's email address
*/
@GET
@Path("get-email")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Read the user's email address", notes="Read the user's email address. The user is the one owning the token",
response=ResponseBean.class, nickname="get-email")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The user's email value is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The user's email is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserEmail(){
Caller caller = AuthorizationProvider.instance.get();
@ -237,14 +196,18 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* Get the profile associated to the token
* @responseExample application/json { "success" : true, "message" : null, "result" : { "user_id" : 23769487, "username" : "john.smith", "email" : "********", "first_name" : "John", "middle_name" : "", "last_name" : "Smith", "fullname" : "John Smith", "registration_date" : 1475151491415, "user_avatar_url" : "https://******D", "male" : true, "job_title" : "", "location_industry" : "no", "custom_attrs_map" : null, "email_addresses" : [ ], "screen_name" : "john.smith", "user_avatar_id" : "https://****sY%3D" } }
* @return the user's profile. The user is the one owning the token
*/
@GET
@Path("get-profile")
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Read the user's profile", notes="Read the user's profile. The user is the one owning the token",
response=ResponseBean.class, nickname="get-profile")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The user's profile is reported in the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The user's profile is reported in the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserProfile(){
Caller caller = AuthorizationProvider.instance.get();
@ -253,10 +216,10 @@ public class Users {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
if(!TokensUtils.isUserTokenDefault(caller)){
if(!TokensUtils.isUserToken(caller)){
status = Status.FORBIDDEN;
responseBean.setMessage(NOT_USER_TOKEN_CONTEXT_USED);
logger.warn("Trying to access users method via a token different than USER is not allowed");
responseBean.setMessage("User's information can only be retrieved through a user Jtoken");
logger.warn("Trying to access users method via a token different than 'user-token' is not allowed");
}else{
try{
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
@ -271,7 +234,7 @@ public class Users {
}
return Response.status(status).entity(responseBean).build();
}
private static final Function<GCubeUser, UserProfileExtendedWithVerifiedEmail> GCUBE_TO_EXTENDED_PROFILE_MAP_WITH_VERIFIED_EMAIL
= new Function<GCubeUser, UserProfileExtendedWithVerifiedEmail>() {
@ -293,7 +256,24 @@ public class Users {
return profile;
}
};
/**
* @responseExample application/json {
"id": "john.smith",
"roles": [],
"picture": "https://***gAJ4uVWTA74xwQ6%2FCA72RRinysY%3D",
"name": "John Smith",
"middle_name": "",
"male": true,
"location_industry": "no",
"given_name": "John",
"email": "******",
"job_title": "",
"family_name": "Smith",
"verified_email": true
}
* @return the user's profile compliant with oauth
*/
@GET
@Path("get-oauth-profile")
@Produces(MediaType.APPLICATION_JSON)
@ -305,7 +285,7 @@ public class Users {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
UserProfileExtendedWithVerifiedEmail userWithEmailVerified = null;
if(! (TokensUtils.isUserTokenDefault(caller) || TokensUtils.isUserTokenQualified(caller))){
if(!TokensUtils.isUserToken(caller)){
status = Status.FORBIDDEN;
responseBean.setMessage(NOT_USER_TOKEN_CONTEXT_USED);
logger.warn("Trying to access users method via a token different than USER is not allowed");
@ -335,15 +315,25 @@ public class Users {
return Response.status(status).entity(userWithEmailVerified).build();
}
/**
* @responseExample application/json {
"success": true,
"message": null,
"result": [
"john.smith",
"marco.polo"
]
}
* Get the list of usernames belonging to a given context
* @return the list of usernames for the user belonging to the context linked to the provided auth token
*/
@GET
@Path("get-all-usernames")
@ApiOperation(value = "Get the list of usernames belonging to a given context", notes="Retrieve the list of usernames for the user belonging to the context linked to the provided token.",
response=ResponseBean.class, nickname="get-all-usernames")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The list of usernames is put into the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list of usernames is put into the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getAllUserNames(){
ResponseBean responseBean = new ResponseBean();
@ -384,13 +374,16 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* Get the map of couples username/fullname of the users belonging to a given context
* @return the map of couples username/fullname of the users belonging to the context linked to the provided token.
*/
@GET
@Path("get-all-fullnames-and-usernames")
@ApiOperation(value = "Get the map of couples username/fullname of the users belonging to a given context", notes="Get the map of couples username/fullname of the users belonging to the context linked to the provided token.",
response=ResponseBean.class, nickname="get-all-fullnames-and-usernames")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The map is put into the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The map is put into the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
@Produces(MediaType.APPLICATION_JSON)
public Response getFullnamesAndUsernames(){
@ -432,16 +425,19 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* Get the list of users having a given global-role, e.g. 'Administrator'. (Legacy)
* @param roleName the name of the role to be checked (e.g. Administrator)
* @return the list of users having a given global-role
*/
@GET
@Path("get-usernames-by-global-role")
@ApiOperation(value = "Get the list of users having a given global-role", notes="Get the list of users having a given global-role, e.g. 'Administrator'.",
response=ResponseBean.class, nickname="get-usernames-by-global-role")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The list is put into the 'result' field of the returned object", response = ResponseBean.class),
@ApiResponse(code = 500, message = ErrorMessages.ERROR_IN_API_RESULT, response=ResponseBean.class)})
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes ({
@ResponseCode ( code = 200, condition = "The list is put into the 'result' field of the returned object"),
@ResponseCode ( code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUsernamesByGlobalRole(
@ApiParam(value = "role-name: the name of the role to be checked (e.g. Administrator)", required = true)
@QueryParam("role-name") String roleName){
ResponseBean responseBean = new ResponseBean();
@ -482,63 +478,86 @@ public class Users {
return Response.status(status).entity(responseBean).build();
}
/**
* @pathExample /get-usernames-by-role?role-name=VRE-Manager
* @param roleName the role name
* @return the usernames having the role in the VRE
* @responseExample application/json {
"success": true,
"message": null,
"result": [
"john.smith",
"marco.polo"
]
}
*/
@GET
@Path("get-usernames-by-role")
@Produces(MediaType.APPLICATION_JSON)
public Response getUsernamesByRole(
@QueryParam("role-name") String roleName){
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
String context = ScopeProvider.instance.get();
KeycloakAPICredentials apiService = KeycloakAPICredentials.getSingleton();
Keycloak keycloak;
keycloak = KeycloakBuilder.builder()
.serverUrl(apiService.getServerURL())
.realm(apiService.getRealm())
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.clientId(apiService.getClientid()) //
.clientSecret(apiService.getPassword()).build();
List<String> usernames = new ArrayList<String>();
try{
GroupManager groupManager = GroupManagerWSBuilder.getInstance().getGroupManager();
RoleManager roleManager = RoleManagerWSBuilder.getInstance().getRoleManager();
long roleId = roleManager.getRoleIdByName(roleName);
if(roleId > 0){
UserManager userManager = UserManagerWSBuilder.getInstance().getUserManager();
List<GCubeUser> users = null;
long groupId = groupManager.getGroupIdFromInfrastructureScope(context);
// first check if for any reason this is a global role, then (if result is null or exception arises) check for site role
// Global role's users are retrieved much faster
try{
if(GLOBAL_ROLES_ALLOWED_BY_LOCAL_CALL_METHOD.contains(roleName)){
// TODO inconsistent value can be returned
users = userManager.listUsersByGlobalRole(roleId);
}
}catch(Exception globalExp){
logger.warn("Failed while checking for global role... trying with local one", globalExp);
try {
List<UserRepresentation> users = searchByRole(keycloak, apiService.getRealm(), context, roleName);
if(users != null){
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
}
if(users == null || users.isEmpty()){
logger.debug("User list is still null/empty, checking for local information");
users = userManager.listUsersByGroupAndRole(groupId, roleId);
}
if(users != null){
for (GCubeUser gCubeUser : users) {
usernames.add(gCubeUser.getUsername());
}
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
}else{
responseBean.setMessage("No role exists whit such a name");
status = Status.BAD_REQUEST;
}
}catch(Exception e){
logger.error("Unable to retrieve user's usernames", e);
responseBean.setResult(usernames);
responseBean.setSuccess(true);
} catch(Exception e){
logger.error("Unable to retrieve user with the requested role", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
private static List<UserRepresentation> searchByRole(Keycloak keycloak, String realmName, String context, String roleName) {
logger.info("Searching by role: {}", roleName);
String clientIdContext = context.replace("/", "%2F") ;
List<ClientRepresentation> clients = keycloak.realm(realmName)
.clients().findByClientId(clientIdContext);
String id = "";
for (ClientRepresentation client : clients) {
logger.info("found client ="+client.getClientId());
logger.info("found client id="+client.getId());
id =client.getId();
}
List<UserRepresentation> users = keycloak.realm(realmName)
.clients()
.get(id).roles().get(roleName)
.getUserMembers(0, 100000);
return users;
}
@GET
@Path("user-exists")
@Produces(MediaType.APPLICATION_JSON)
@Deprecated
public Response existUser(@QueryParam("username") String username){
ResponseBean responseBean = new ResponseBean();

View File

@ -1,8 +1,5 @@
package org.gcube.portal.social.networking.ws.methods.v2;
import io.swagger.annotations.Api;
import io.swagger.annotations.Authorization;
import java.util.List;
import javax.validation.ValidationException;
@ -20,8 +17,6 @@ import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.RoleManagerWSBuilder;
import org.gcube.portal.social.networking.liferay.ws.UserManagerWSBuilder;
import org.gcube.portal.social.networking.swagger.config.Bootstrap;
import org.gcube.portal.social.networking.swagger.config.SwaggerConstants;
import org.gcube.portal.social.networking.ws.outputs.ResponseBean;
import org.gcube.portal.social.networking.ws.utils.TokensUtils;
import org.gcube.vomanagement.usermanagement.GroupManager;
@ -34,18 +29,42 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
/**
* REST interface for the social networking library (vres).
* @author Costantino Perciante at ISTI-CNR
*/
@Path("2/vres")
@Api(value=SwaggerConstants.VRES, authorizations={@Authorization(value = Bootstrap.GCUBE_TOKEN_IN_QUERY_DEF), @Authorization(value = Bootstrap.GCUBE_TOKEN_IN_HEADER_DEF)})
@RequestHeaders ({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader( name = "Content-Type", description = "application/json")
})
public class VREs {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Users.class);
/**
* @responseExample application/json {
"success" : true,
"message" : null,
"result" : [ {
"name" : "NextNext",
"context" : "/gcube/devNext/NextNext",
"description" : "NextNext description AAA"
}, {
"name" : "devVRE",
"context" : "/gcube/devsec/devVRE",
"description" : "devVRE description BBB"
} ]
}
* @pathExample /get-my-vres?getManagers=false
* @param getManagers set true if you also want to know the VRE-Managers
* @return the list of vres along with some metadata
* @throws ValidationException
*/
@SuppressWarnings("unchecked")
@GET
@Path("get-my-vres/")

View File

@ -1,27 +1,26 @@
package org.gcube.portal.social.networking.ws.outputs;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
/**
* Response bean
* @author Costantino Perciante at ISTI-CNR
* (costantino.perciante@isti.cnr.it)
*
*/
@ApiModel(description="A response object", value="Response")
public class ResponseBean implements Serializable {
private static final long serialVersionUID = -2725238162673879658L;
@ApiModelProperty(value="The result of the request: true if it succeeded, false otherwise")
/**
* The result of the request: true if it succeeded, false otherwise
*/
private boolean success;
@ApiModelProperty(value="An error message if something wrong happened, null/empty otherwise")
/**
* An error message if something wrong happened, null/empty otherwise
*/
private String message;
@ApiModelProperty(value="The result object of the request")
/**
* The result object of the request
*/
private Object result;
public ResponseBean() {
@ -32,8 +31,7 @@ public class ResponseBean implements Serializable {
* @param success
* @param message
* @param result
* @param help
*/
*/
public ResponseBean(boolean success, String message, Object result) {
super();
this.success = success;

View File

@ -1,46 +0,0 @@
package org.gcube.portal.social.networking.ws.providers;
import java.io.IOException;
import org.gcube.portal.databook.shared.JobStatusType;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
/**
* Deserializer used to map a string representing the status in this JobNotificationBean to the JobStatusType enum.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class JobStatusTypeDeserializer extends JsonDeserializer<JobStatusType>{
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JobStatusTypeDeserializer.class);
@Override
public JobStatusType deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException,
JsonProcessingException {
logger.debug("Status deserializer called");
String status = p.getText();
JobStatusType toReturn = null;
logger.debug("Status coming from json object is " + status);
JobStatusType[] values = JobStatusType.values();
for (JobStatusType jobStatusType : values) {
if(jobStatusType.toString().toLowerCase().contains(status.toLowerCase())){
toReturn = jobStatusType;
break;
}
}
logger.debug("JOB STATUS deserialized as " + toReturn);
return toReturn;
}
}

View File

@ -17,4 +17,5 @@ public class ErrorMessages {
public static final String BAD_REQUEST = "Please check the parameter you passed, it seems a bad request";
public static final String ERROR_IN_API_RESULT = "The error is reported into the 'message' field of the returned object";
public static final String POST_OUTSIDE_VRE = "A post cannot be written into a context that is not a VRE";
public static final String DEPRECATED_METHOD = "This method is deprecated, must use version 2";
}

View File

@ -8,6 +8,7 @@ import org.gcube.portal.databook.server.DatabookStore;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.EnhancedFeed;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.social.networking.liferay.ws.GroupManagerWSBuilder;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.exception.GroupRetrievalFault;
@ -88,10 +89,11 @@ public class Filters {
* If the initial context is the root: all feeds are returned;
* If the initial context is a VO: feeds for vres within the vo are returned;
* If the initial context is a vre: feeds of the vre are returned;
* @param retrievedLikedFeeds
* @param feeds
* @param context
* @throws Exception
*/
@Deprecated
public static void filterFeedsPerContext(List<Feed> feeds, String context) throws Exception {
List<String> contexts = getContexts(context);
@ -104,6 +106,27 @@ public class Filters {
iterator.remove();
}
}
/**
* Given a list of not filtered posts, the methods remove posts unaccessible in this scope.
* If the initial context is the root: all posts are returned;
* If the initial context is a VO: posts for vres within the vo are returned;
* If the initial context is a vre: posts of the vre are returned;
* @param context
* @throws Exception
*/
public static void filterPostsPerContext(List<Post> posts, String context) throws Exception {
List<String> contexts = getContexts(context);
// filter
Iterator<Post> iterator = posts.iterator();
while (iterator.hasNext()) {
Post post = (Post) iterator.next();
if(!contexts.contains(post.getVreid()))
iterator.remove();
}
}
/**
@ -137,7 +160,7 @@ public class Filters {
/**
* Depending on the type of object provided (e.g. Feed, Comment etc), some information are removed
* @param comments
* @param toClear
* @throws Exception
*/
public static <T> void hideSensitiveInformation(List<T> toClear, String usernameCaller){

View File

@ -6,8 +6,12 @@ import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
@ -24,11 +28,15 @@ import org.gcube.common.resources.gcore.utils.XPathHelper;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.portal.databook.shared.ApplicationProfile;
import org.gcube.portal.databook.shared.Feed;
import org.gcube.portal.databook.shared.FeedType;
import org.gcube.portal.databook.shared.Comment;
import org.gcube.portal.databook.shared.Like;
import org.gcube.portal.databook.shared.Post;
import org.gcube.portal.databook.shared.PostType;
import org.gcube.portal.databook.shared.PrivacyLevel;
import org.gcube.portal.databook.shared.ex.FeedIDNotFoundException;
import org.gcube.portal.notifications.bean.GenericItemBean;
import org.gcube.portal.notifications.thread.CommentNotificationsThread;
import org.gcube.portal.notifications.thread.LikeNotificationsThread;
import org.gcube.portal.notifications.thread.MentionNotificationsThread;
import org.gcube.portal.notifications.thread.PostNotificationsThread;
import org.gcube.portal.social.networking.caches.SocialNetworkingSiteFinder;
@ -42,6 +50,10 @@ import org.gcube.social_networking.socialutillibrary.Utils;
import org.gcube.socialnetworking.socialtoken.SocialMessageParser;
import org.gcube.vomanagement.usermanagement.GroupManager;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.exception.TeamRetrievalFault;
import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException;
import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
@ -49,14 +61,16 @@ import org.xml.sax.InputSource;
/**
* Utility class.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
@SuppressWarnings("deprecation")
public class SocialUtils {
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialUtils.class);
public final static String NO_TEXT_FILE_SHARE = "_N0_73X7_SH4R3_";
public final static int CACHING_TIME_TO_EXPIRATION = 2506000;//29 days 6 minutes 40 seconds
public final static String DISABLED_USERS_NOTIFICATIONS_NAMESPACE = "dun:";
// name of the portlet for vre notification
public static final String NEWS_FEED_PORTLET_CLASSNAME = "org.gcube.portlets.user.newsfeed.server.NewsServiceImpl";
@ -94,14 +108,14 @@ public class SocialUtils {
/**
* Method used when an application needs to publish something.
* @param feedText
* @param postText
* @param uriParams
* @param previewTitle
* @param previewDescription
* @param httpImageUrl
* @return true upon success, false on failure
*/
public static Feed shareApplicationUpdate(
public static Post shareApplicationUpdate(
String postText,
String uriParams,
String previewTitle,
@ -126,7 +140,7 @@ public class SocialUtils {
String scope = ScopeProvider.instance.get();
String appId = caller.getClient().getId();
Feed toWrite =
Post toWrite =
buildPost(
escapedPostText,
uriParams == null ? "" : uriParams,
@ -137,7 +151,7 @@ public class SocialUtils {
scope);
// try to save it
boolean res = CassandraConnection.getInstance().getDatabookStore().saveAppFeed(toWrite);
boolean res = CassandraConnection.getInstance().getDatabookStore().saveAppPost(toWrite);
if(res){
logger.info("Feed correctly written by application " + appId);
@ -215,7 +229,7 @@ public class SocialUtils {
* @param previewThumbnailUrl the image url to show in the preview
* @return a feed instance ready to be written
*/
private static Feed buildPost(
private static Post buildPost(
String description,
String uriParams,
String previewTitle,
@ -230,9 +244,9 @@ public class SocialUtils {
if (uriParams != null && uriParams.compareTo("") != 0)
uri += "?"+uriParams;
Feed toReturn = new Feed(
Post toReturn = new Post(
UUID.randomUUID().toString(),
FeedType.PUBLISH,
PostType.PUBLISH,
applicationProfile.getKey(),
new Date(),
scopeApp,
@ -371,7 +385,7 @@ public class SocialUtils {
* @param notifyGroup
* @return The written Feed
*/
public static Feed shareUserUpdate(
public static Post shareUserUpdate(
String userId,
String postText,
String vreId,
@ -422,12 +436,12 @@ public class SocialUtils {
textToPost = escapedPostText;
}
Feed toShare = new Feed(UUID.randomUUID().toString(), FeedType.PUBLISH, userId, new Date(),
Post toShare = new Post(UUID.randomUUID().toString(), PostType.PUBLISH, userId, new Date(),
vreId, url, urlThumbnail, textToPost, PrivacyLevel.SINGLE_VRE, fullName, email, thumbnailURL, linkTitle, linkDesc, host);
logger.info("Attempting to save Post with text: " + textToPost + " Level = " + PrivacyLevel.SINGLE_VRE + " Timeline = " + vreId);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserFeed(toShare);
boolean result = CassandraConnection.getInstance().getDatabookStore().saveUserPost(toShare);
if(vreId != null && vreId.compareTo("") != 0 && result) {
@ -494,4 +508,218 @@ public class SocialUtils {
}
return toShare;
}
/**
* Allows to comment post in a certain vre.
* @param userid the username
* @param time the date and time of the comment
* @param postId the key of the post that was commented
* @param commentText the text as it is, it will be parsed
* @param postOwnerId the username of the user who created the post that was commented
* @param context the VRE context
*
* @return the Comment instance if ok, null if somwthign went KO
* @throws FeedIDNotFoundException
*/
public static Comment commentPost(String userid, Date time, String postId, String commentText, String postOwnerId, String context) throws FeedIDNotFoundException {
SocialMessageParser messageParser = new SocialMessageParser(commentText);
String escapedCommentText = messageParser.getParsedMessage();
//check if any mention exists
ArrayList<GenericItemBean> mentionedUsers = getUsersFromUsernames(Utils.getMentionedUsernames(commentText));
ArrayList<ItemBean> mentionedUsersToConvertInHTML = convertToItemBean(mentionedUsers);
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get());
escapedCommentText = Utils.convertMentionUsernamesAnchorHTML(escapedCommentText, mentionedUsersToConvertInHTML, site.getSiteURL(), site.getSiteLandingPagePath());
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
try {
user = uManager.getUserByUsername(userid);
} catch(Exception e){
logger.error("Unable to get user informations, comment write fails.", e);
return null;
}
String commentKey = UUID.randomUUID().toString(); // a unique id that goes in the DB
String email = user.getEmail();
String fullName = user.getFirstName() + " " + user.getLastName();
String thumbnailURL = user.getUserAvatarURL();
Comment theComment = new Comment(commentKey, userid, time, postId, escapedCommentText, fullName, thumbnailURL);
logger.info("Attempting to save Comment with text: " + commentText + " postid="+postId);
boolean result = CassandraConnection.getInstance().getDatabookStore().addComment(theComment);
logger.info("Added comment? " + theComment.toString() + " Result is " +result);
if (!result)
return null;
//if the comment was correctly delivered notify users involved
SocialNetworkingUser socialUser = new SocialNetworkingUser(userid, email, fullName, thumbnailURL);
NotificationsManager nm = new ApplicationNotificationsManager(uManager, site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME);
//if the user who commented this post is not the user who posted it notify the poster user (Post owner)
logger.info("The post creator is " + postOwnerId);
if (! user.getUsername().equals(postOwnerId)) {
boolean resultNotifyOwnComment = nm.notifyOwnCommentReply(postOwnerId, postId, escapedCommentText, theComment.getKey());
logger.info("Comment Notification to post creator added? " + resultNotifyOwnComment);
}
//if there are users who liked this post they get notified, asynchronously with this thread
ArrayList<Like> likes = getAllLikesByPost(postId);
Thread likesThread = new Thread(new LikeNotificationsThread(escapedCommentText, nm, likes, postOwnerId, theComment.getKey()));
likesThread.start();
//notify the other users who commented this post (excluding the ones above)
Thread commentsNotificationthread = new Thread(new CommentNotificationsThread(
CassandraConnection.getInstance().getDatabookStore(),
uManager, user.getUsername(), theComment.getFeedid(), escapedCommentText, nm, postOwnerId, theComment.getKey(), likes));
commentsNotificationthread.start();
//send the notification to the mentioned users, if any
if (mentionedUsers != null && mentionedUsers.size() > 0) {
ArrayList<GenericItemBean> toPass = new ArrayList<GenericItemBean>();
// among the mentionedUsers there could be groups of people
Map<String, ItemBean> uniqueUsersToNotify = new HashMap<>();
UserManager um = new LiferayUserManager();
for (ItemBean bean : mentionedUsersToConvertInHTML) {
if(bean.isItemGroup()){
// retrieve the users of this group
try {
List<GCubeUser> teamUsers = um.listUsersByTeam(Long.parseLong(bean.getId()));
for (GCubeUser userTeam : teamUsers) {
if(!uniqueUsersToNotify.containsKey(userTeam.getUsername()))
uniqueUsersToNotify.put(userTeam.getUsername(), new ItemBean(userTeam.getUserId()+"",
userTeam.getUsername(), userTeam.getFullname(), userTeam.getUserAvatarURL()));
}
} catch (NumberFormatException
| UserManagementSystemException
| TeamRetrievalFault | UserRetrievalFault e) {
logger.error("Unable to retrieve team information", e);
}
}else{
// it is a user, just add to the hashmap
if(!uniqueUsersToNotify.containsKey(bean.getName()))
uniqueUsersToNotify.put(bean.getName(), bean);
}
}
// iterate over the hashmap
Iterator<Entry<String, ItemBean>> userMapIterator = uniqueUsersToNotify.entrySet().iterator();
while (userMapIterator.hasNext()) {
Map.Entry<String, ItemBean> userEntry = (Map.Entry<String, ItemBean>) userMapIterator
.next();
ItemBean userBean = userEntry.getValue();
toPass.add(new GenericItemBean(userBean.getId(), userBean.getName(), userBean.getAlternativeName(), userBean.getThumbnailURL()));
}
Thread thread = new Thread(new MentionNotificationsThread(theComment.getFeedid(), escapedCommentText, nm, null, toPass));
thread.start();
}
return theComment;
}
private static ArrayList<Like> getAllLikesByPost(String postid) {
ArrayList<Like> toReturn = (ArrayList<Like>) CassandraConnection.getInstance().getDatabookStore().getAllLikesByPost(postid);
logger.debug("Asking likes for " + postid);
for (Like like : toReturn) {
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
try {
user = uManager.getUserByUsername(like.getUserid());
} catch(Exception e){
logger.error("Unable to get user informations, comment write fails.", e);
return null;
}
String thumbnailURL = user.getUserAvatarURL();
like.setThumbnailURL(thumbnailURL == null ? "" : thumbnailURL);
}
return toReturn;
}
public static boolean like(String username, String postid, String context) {
boolean likeCommitResult = false;
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
try {
user = uManager.getUserByUsername(username);
} catch(Exception e){
logger.error("Unable to get user informations, like write fails.", e);
return false;
}
String email = user.getEmail();
String fullName = user.getFirstName() + " " + user.getLastName();
String thumbnailURL = user.getUserAvatarURL();
SocialNetworkingUser socialUser = new SocialNetworkingUser(user.getUsername(), email, fullName, thumbnailURL);
Like toLike = new Like(UUID.randomUUID().toString(), user.getUsername(),
new Date(), postid, user.getFullname(), user.getUserAvatarURL());
Post thePost = null;
try {
logger.info("Attempting to read post with id: " +postid);
thePost = CassandraConnection.getInstance().getDatabookStore().readPost(postid);
likeCommitResult = CassandraConnection.getInstance().getDatabookStore().like(toLike);
} catch (Exception e) {
logger.error("Post not found for this like ot could not like the post " + e.getMessage());
return false;
}
//if the like was correctly delivered notify the user who made the post
boolean resultNotifyLike =false;
if (likeCommitResult) {
SocialNetworkingSite site = SocialNetworkingSiteFinder.getSocialNetworkingSiteFromScope(ScopeProvider.instance.get());
NotificationsManager nm = new ApplicationNotificationsManager(UserManagerWSBuilder.getInstance().getUserManager(), site, context, socialUser, NEWS_FEED_PORTLET_CLASSNAME);
String postText = thePost.getDescription();
String postOwnerId = thePost.getEntityId();
SocialMessageParser messageParser = new SocialMessageParser(postText);
String escapedPostText = messageParser.getParsedMessage();
//if the user who liked this post is not the user who posted it notify the poster user (Post owner)
logger.info("The post creator is " + postOwnerId);
if (! user.getUsername().equals(postOwnerId)) {
resultNotifyLike = nm.notifyLikedPost(postOwnerId, postid, escapedPostText);
logger.info("Like Notification to post creator added? " + resultNotifyLike);
}
}
return likeCommitResult && resultNotifyLike;
}
public static boolean unlike(String username, String likeid, String postid) {
boolean unlikeCommitResult = false;
// retrieve user information
GCubeUser user;
UserManager uManager = UserManagerWSBuilder.getInstance().getUserManager();
try {
user = uManager.getUserByUsername(username);
} catch(Exception e){
logger.error("Unable to get user informations, unlike write fails.", e);
return false;
}
String fullName = user.getFirstName() + " " + user.getLastName();
String thumbnailURL = user.getUserAvatarURL();
try {
unlikeCommitResult = CassandraConnection.getInstance().getDatabookStore().unlike(username, likeid, postid);
} catch (Exception e) {
logger.error("Post not Found for this like ot could not unlike the post " + e.getMessage());
return false;
}
return unlikeCommitResult;
}
}

View File

@ -2,17 +2,18 @@ package org.gcube.portal.social.networking.ws.utils;
import org.gcube.common.authorization.library.ClientType;
import org.gcube.common.authorization.library.utils.Caller;
import org.slf4j.LoggerFactory;
/**
* Tokens utils methods
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class TokensUtils {
// a user context token (not qualified) has as qualifier the word "TOKEN"
private static final String DEFAULT_QUALIFIER_USER_TOKEN = "TOKEN";
// Logger
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TokensUtils.class);
/**
* Check if it is a service token
* @return a boolean value
@ -28,7 +29,10 @@ public class TokensUtils {
* @return a boolean value
*/
public static boolean isApplicationToken(Caller caller){
String username = caller.getClient().getId();
if (username.startsWith("service-account-")) {
return true;
}
return caller.getClient().getType().equals(ClientType.EXTERNALSERVICE);
}
@ -47,8 +51,12 @@ public class TokensUtils {
* Check if it is a user token
* @return a boolean value
*/
public static boolean isUserToken(Caller caller){
public static boolean isUserToken(Caller caller) {
logger.debug("\n ****** \n isUserToken: caller.getClient().getType().equals(ClientType.USER) => " + caller.getClient().getType().equals(ClientType.USER));
String username = caller.getClient().getId();
if (username.startsWith("service-account-")) {
return false;
}
return caller.getClient().getType().equals(ClientType.USER);
}
@ -58,9 +66,7 @@ public class TokensUtils {
* @return a boolean value
*/
public static boolean isUserTokenDefault(Caller caller){
return caller.getClient().getType().equals(ClientType.USER) && caller.getTokenQualifier().equals(DEFAULT_QUALIFIER_USER_TOKEN);
return isUserToken(caller);
}
/**

File diff suppressed because it is too large Load Diff

1
src/main/webapp/WEB-INF/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/web.xml

View File

@ -1,11 +1,9 @@
<application mode='online'>
<name>SocialNetworking</name>
<group>Portal</group>
<version>2.1.0-SNAPSHOT</version>
<version>2.5.0-SNAPSHOT</version>
<description>SocialNetworking Service</description>
<local-persistence location='target' />
<exclude>/rest/</exclude>
<exclude>/rest/swagger.yaml</exclude>
<exclude>/rest/swagger.json</exclude>
<exclude>/rest/application.wadl</exclude>
<exclude>/api-docs/*</exclude>
<exclude>/docs/*</exclude>
</application>

View File

@ -15,19 +15,12 @@
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
org.gcube.portal.social.networking
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>SwaggerBootstrap</servlet-name>
<servlet-class>org.gcube.portal.social.networking.swagger.config.Bootstrap</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>

View File

@ -0,0 +1,26 @@
.d4science_intro {
top: 0;
z-index: 2000;
position: fixed;
display: block ruby;
padding: 10px;
background: white;
width: 100%;
height: 100px;
}
.navbar-fixed-top {
top: 100px !important;
}
.sidebar {
top: 160px !important;
}
.navbar {
margin-bottom: 40px !important;
}
.main {
top: 90px;
}

View File

@ -1,201 +0,0 @@
package org.gcube.portal.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
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.protocol.HttpClientContext;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portal.social.networking.liferay.ws.LiferayJSONWsCredentials;
import org.gcube.portal.social.networking.ws.inputs.MessageInputBean;
import org.gcube.portal.social.networking.ws.inputs.Recipient;
import org.json.simple.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JTests {
private static final String YOUR_TOKEN_HERE = "";
private static final String METHOD = "messages/writeMessageToUsers";
private static final String SCOPE = "/gcube";
//@Test
public void readSocialServiceEndPoint() throws Exception {
String findInContext = SCOPE;
ScopeProvider.instance.set(findInContext);
ServiceEndPointReaderSocial readerSE = new ServiceEndPointReaderSocial(findInContext);
System.out.println("Found base path " + readerSE.getBasePath());
}
//@Test
public void testWithApacheClient() throws Exception {
ServiceEndPointReaderSocial reader = new ServiceEndPointReaderSocial(SCOPE);
String requestForMessage = reader.getBasePath() + METHOD + "?gcube-token=" + YOUR_TOKEN_HERE;
requestForMessage = requestForMessage.replace("http", "https"); // remove the port (or set it to 443) otherwise you get an SSL error
System.out.println("Request url is going to be " + requestForMessage);
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
HttpPost postRequest = new HttpPost(requestForMessage);
// put the sender, the recipients, subject and body of the mail here
StringEntity input = new StringEntity("sender=andrea.rossi&recipients=gianpaolo.coro&subject=Sample mail&body=Sample mail object");
input.setContentType("application/x-www-form-urlencoded");
postRequest.setEntity(input);
HttpResponse response = client.execute(postRequest);
System.out.println("Error is " + response.getStatusLine().getReasonPhrase());
if (response.getStatusLine().getStatusCode() != 201) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
}
System.out.println(response.toString());
}catch(Exception e){
System.err.println("error while performing post method " + e.toString());
}
}
//@Test
public void parserJSON() throws IOException{
MessageInputBean message = new MessageInputBean();
message.setBody("a caso");
message.setSubject("subject");
ArrayList<Recipient> recipients = new ArrayList<Recipient>();
Recipient recipient = new Recipient("recipient1");
recipients.add(recipient);
message.setRecipients(recipients);
//Object mapper instance
ObjectMapper mapper = new ObjectMapper();
//Convert POJO to JSON
String json = mapper.writeValueAsString(message);
MessageInputBean obje = mapper.readValue(json, MessageInputBean.class);
System.out.println(json);
System.out.println(obje);
}
//@Test
public void callLiferayWS() throws Exception{
HttpHost target = new HttpHost("localhost", 8080, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(target.getHostName(), target.getPort()),
new UsernamePasswordCredentials("test@liferay.com", "random321"));
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider).build();
try {
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local
// auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(target, basicAuth);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpGet httpget = new HttpGet("/api/jsonws" + "/user/get-user-by-screen-name/company-id/20155/screen-name/costantino.perciante");
System.out.println("Executing request " + httpget.getRequestLine() + " to target " + target);
CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
//@Test
public void retrieveCredentials(){
ScopeProvider.instance.set("/gcube");
LiferayJSONWsCredentials cred = LiferayJSONWsCredentials.getSingleton();
System.out.println("Password is " + cred.getPassword());
System.out.println("Host is " + cred.getHost());
}
//@Test
public void readGcoreEndPoint() throws Exception{
GcoreEndpointReader reader = new GcoreEndpointReader("/gcube");
reader.getResourceEntyName();
}
//@Test
public void sendNotification() throws ClientProtocolException, IOException{
String url ="https://socialnetworking-d-d4s.d4science.org/social-networking-library-ws/rest//2/notifications/notify-job-status?gcube-token=07f5f961-d0e0-4bc4-af90-a305e8b63ac7-98187548";
CloseableHttpClient client = HttpClientBuilder.create().build();
JSONObject obj = new JSONObject();
obj.put("job_id", "bbbbb");
obj.put("recipient", "costantino.perciante");
obj.put("job_name", "aaaaaa");
obj.put("service_name", "Test");
obj.put("status", "SUCCEEDED");
HttpPost request = new HttpPost(url);
request.addHeader("Content-type", ContentType.APPLICATION_JSON.toString());
StringEntity paramsEntity = new StringEntity(obj.toJSONString(), ContentType.APPLICATION_JSON);
request.setEntity(paramsEntity);
client.execute(request);
}
}