From 83c50406ed405f675159419feb8389c0d8f62149 Mon Sep 17 00:00:00 2001 From: Guus der Kinderen Date: Fri, 4 Jul 2025 12:58:54 +0200 Subject: [PATCH] fixes #7: Add support for vCards To generate the HTML version, I took the Markdown version, which I added to the webapp of https://stackedit.io/ Next, I exported the stackedit-generated page as HTML, using their "Stylized HTML with TOC" template. I've only changed the HTML title in the generated file. --- changelog.html | 6 +- plugin.xml | 2 +- pom.xml | 2 +- readme.html | 700 +++++++++--------- readme.md | 142 ++++ .../controller/UserServiceController.java | 86 +++ .../plugin/rest/service/JerseyWrapper.java | 3 +- .../plugin/rest/service/UserVCardService.java | 103 +++ 8 files changed, 707 insertions(+), 337 deletions(-) create mode 100644 src/java/org/jivesoftware/openfire/plugin/rest/service/UserVCardService.java diff --git a/changelog.html b/changelog.html index e4902ac8b..717de8854 100644 --- a/changelog.html +++ b/changelog.html @@ -44,10 +44,12 @@

REST API Plugin Changelog

-

1.11.1 (tbd)

+

1.12.0 (tbd)

diff --git a/plugin.xml b/plugin.xml index c87fe275f..bfecac935 100644 --- a/plugin.xml +++ b/plugin.xml @@ -6,7 +6,7 @@ Allows administration over a RESTful API. Roman Soldatow ${project.version} - 2024-11-17 + 2025-07-04 5.0.0 diff --git a/pom.xml b/pom.xml index 60cbe24f7..2f71808ac 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.igniterealtime.openfire.plugins restAPI - 1.11.1-SNAPSHOT + 1.12.0-SNAPSHOT REST API Plugin Allows administration over a RESTful API. diff --git a/readme.html b/readme.html index 0f771656a..2f5219b73 100644 --- a/readme.html +++ b/readme.html @@ -4,7 +4,7 @@ - test + Openfire REST API Plugin Readme @@ -27,36 +27,39 @@
  • User related REST Endpoints
  • Chat room related REST Endpoints
  • System related REST Endpoints

    Installation

    Copy restAPI.jar into the plugins directory of your Openfire server. The plugin will be automatically deployed. To upgrade to a newer version, overwrite the restAPI.jar file with the new one.

    - -

    - Important Step: To enable the plugin make sure to set the system property adminConsole.access.allow-wildcards-in-excludes to true. - Without the above step the REST API plugin always redirects to login - This was done in response to a security issue -

    - +

    Important Step: To enable the plugin make sure to set the system property adminConsole.access.allow-wildcards-in-excludes to true

    +

    Without the above step the REST API plugin always redirects to login.
    + This was done in response to a security issue.

    Explanation of REST

    To provide a standard way of accessing the data the plugin is using REST.

    @@ -287,7 +286,8 @@

    Possible parameters

    GET http://example.org:9090/plugins/restapi/v1/users?propertyKey=keyname&propertyValue=keyvalue

    If you want to get a JSON format result, please add “Accept: application/json” to the Header.

    -

    Retrieve a user Endpoint to get information over a specific user

    +

    Retrieve a user

    +

    Endpoint to get information over a specific user

    GET /users/{username}

    @@ -333,33 +333,31 @@

    XML Examples

    Payload Example 1 (required parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<user>
    - <username>test3</username> <password>p4ssword</password></user>
    +<user>  
    + <username>test3</username> <password>p4ssword</password></user>  
     

    Payload Example 2 (available parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<user>
    - <username>testuser</username> <password>p4ssword</password> <name>Test User</name> <email>test@localhost.de</email> <properties> <property key="keyname" value="value"/> <property key="anotherkey" value="value"/> </properties></user>
    +<user>  
    + <username>testuser</username> <password>p4ssword</password> <name>Test User</name> <email>test@localhost.de</email> <properties> <property key="keyname" value="value"/> <property key="anotherkey" value="value"/> </properties></user>  
     

    JSON Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/json
    - POST http://example.org:9090/plugins/restapi/v1/users

    -
    +

    Header: Content-Type: application/json

    +

    POST http://example.org:9090/plugins/restapi/v1/users

    Payload Example 1 (required parameters):

    {
    - "username": "admin", "password": "p4ssword"}
    + "username": "admin", "password": "p4ssword"}  
     

    Payload Example 2 (available parameters):

    {
    - "username": "admin", "password": "p4ssword", "name": "Administrator", "email": "admin@example.com", "properties": { "property": [ { "@key": "console.rows_per_page", "@value": "user-summary=8" }, { "@key": "console.order", "@value": "session-summary=1" } ] }}
    + "username": "admin", "password": "p4ssword", "name": "Administrator", "email": "admin@example.com", "properties": { "property": [ { "@key": "console.rows_per_page", "@value": "user-summary=8" }, { "@key": "console.order", "@value": "session-summary=1" } ] }}  
     

    REST API Version 1.3.0 and later - Payload Example 3 (available parameters):

    {
    - "users": [ { "username": "admin", "name": "Administrator", "email": "admin@example.com", "password": "p4ssword", "properties": [ { "key": "console.order", "value": "session-summary=0" } ] }, { "username": "test", "name": "Test", "password": "p4ssword" } ]}
    + "users": [ { "username": "admin", "name": "Administrator", "email": "admin@example.com", "password": "p4ssword", "properties": [ { "key": "console.order", "value": "session-summary=0" } ] }, { "username": "test", "name": "Test", "password": "p4ssword" } ]}  
     

    Delete a user

    Endpoint to delete a user

    @@ -390,9 +388,7 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser

    Update a user

    Endpoint to update / rename a user

    @@ -424,46 +420,41 @@

    Possible parameters

    XML Example

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/users/testuser

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/users/testuser

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<user>
    - <username>testuser</username> <name>Test User edit</name> <email>test@edit.de</email> <properties> <property key="keyname" value="value"/> </properties></user>
    +<user>  
    + <username>testuser</username> <name>Test User edit</name> <email>test@edit.de</email> <properties> <property key="keyname" value="value"/> </properties></user>  
     

    Rename Example

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/users/oldUsername

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/users/oldUsername

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<user>
    - <username>newUsername</username> <name>Test User edit</name> <email>test@edit.de</email> <properties> <property key="keyname" value="value"/> </properties></user>
    +<user>  
    + <username>newUsername</username> <name>Test User edit</name> <email>test@edit.de</email> <properties> <property key="keyname" value="value"/> </properties></user>  
     

    JSON Example

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/json
    - PUT http://example.org:9090/plugins/restapi/v1/users/testuser

    -
    +

    Header: Content-Type application/json

    +

    PUT http://example.org:9090/plugins/restapi/v1/users/testuser

    Payload:

    {
    - "username": "testuser", "name": "Test User edit", "email": "test@edit.de", "properties": { "property": { "@key": "keyname", "@value": "value" } }}
    + "username": "testuser", "name": "Test User edit", "email": "test@edit.de", "properties": { "property": { "@key": "keyname", "@value": "value" } }}  
     

    REST API Version 1.3.0 and later - Payload Example 2 (available parameters):

    {
    - "username": "testuser", "name": "Test User edit", "email": "test@edit.de", "properties": [ { "key": "keyname", "value": "value" } ]}
    + "username": "testuser", "name": "Test User edit", "email": "test@edit.de", "properties": [ { "key": "keyname", "value": "value" } ]}  
     
    -

    Retrieve all user groups Endpoint to get group names of a specific user

    +

    Retrieve all user groups

    +

    Endpoint to get group names of a specific user

    GET /users/{username}/groups

    @@ -491,9 +482,7 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    Add user to groups

    Endpoint to add user to a groups

    @@ -524,15 +513,13 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - POST http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    -
    +

    Header: Content-Type application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<groups>
    - <groupname>Admins</groupname> <groupname>Support</groupname></groups>
    +<groups>  
    + <groupname>Admins</groupname> <groupname>Support</groupname></groups>  
     

    Add user to group

    Endpoint to add user to a group

    @@ -569,10 +556,8 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - POST http://example.org:9090/plugins/restapi/v1/users/testuser/groups/testGroup

    -
    +

    Header: Content-Type application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/users/testuser/groups/testGroup

    Delete a user from a groups

    Endpoint to remove a user from a groups

    @@ -603,15 +588,13 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    -
    +

    Header: Content-Type application/xml

    +

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/groups

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<groups>
    - <groupname>Admins</groupname> <groupname>Support</groupname></groups>
    +<groups>  
    + <groupname>Admins</groupname> <groupname>Support</groupname></groups>  
     

    Delete a user from a group

    Endpoint to remove a user from a group

    @@ -648,10 +631,8 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/groups/testGroup

    -
    +

    Header: Content-Type application/xml

    +

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/groups/testGroup

    Lockout a user

    Endpoint to lockout / ban the user from the chat server. The user will be kicked if the user is online.

    @@ -682,11 +663,10 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    POST http://example.org:9090/plugins/restapi/v1/lockouts/testuser

    -
    +

    POST http://example.org:9090/plugins/restapi/v1/lockouts/testuser

    -

    Unlock a user Endpoint to unlock / unban the user

    +

    Unlock a user

    +

    Endpoint to unlock / unban the user

    DELETE /lockouts/{username}

    @@ -714,11 +694,10 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/lockouts/testuser

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/lockouts/testuser

    -

    Retrieve user roster Endpoint to get roster entries (buddies) from a specific user

    +

    Retrieve user roster

    +

    Endpoint to get roster entries (buddies) from a specific user

    GET /users/{username}/roster

    @@ -746,11 +725,10 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/users/testuser/roster

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/users/testuser/roster

    -

    Create a user roster entry Endpoint to add a new roster entry to a user

    +

    Create a user roster entry

    +

    Endpoint to add a new roster entry to a user

    POST /users/{username}/roster

    @@ -778,23 +756,22 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - POST http://example.org:9090/plugins/restapi/v1/users/testuser/roster

    -
    +

    Header: Content-Type application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/users/testuser/roster

    Payload:
    Payload Example 1 (required parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<rosterItem>
    - <jid>peter@pan.de</jid></rosterItem>
    +<rosterItem>  
    + <jid>peter@pan.de</jid></rosterItem>  
     

    Payload Example 2 (available parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<rosterItem>
    - <jid>peter@pan1.de</jid> <nickname>Peter1</nickname> <subscriptionType>3</subscriptionType> <groups> <group>Friends</group> </groups></rosterItem>
    +<rosterItem>  
    + <jid>peter@pan1.de</jid> <nickname>Peter1</nickname> <subscriptionType>3</subscriptionType> <groups> <group>Friends</group> </groups></rosterItem>  
     
    -

    Delete a user roster entry Endpoint to remove a roster entry from a user

    +

    Delete a user roster entry

    +

    Endpoint to remove a roster entry from a user

    DELETE /users/{username}/roster/{jid}

    @@ -828,11 +805,10 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/roster/peter@pan.de

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/roster/peter@pan.de

    -

    Update a user roster entry Endpoint to update a roster entry

    +

    Update a user roster entry

    +

    Endpoint to update a roster entry

    PUT /users/{username}/roster/{jid}

    @@ -866,16 +842,113 @@

    Possible parameters

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/users/testuser/roster/peter@pan.de

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/users/testuser/roster/peter@pan.de

    +
    +

    Payload:

    +
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    +<rosterItem>  
    + <jid>peter@pan.de</jid> <nickname>Peter Pan</nickname> <subscriptionType>0</subscriptionType> <groups> <group>Support</group> </groups></rosterItem>  
    +
    +

    Retrieve user’s vcard

    +

    Endpoint to get the vCard of a particular user

    +
    +

    GET /users/{username}/vcard

    +
    +

    Payload: none

    +

    Return value: vCard XML data

    +

    Possible parameters

    + + + + + + + + + + + + + + + + + + +
    ParameterParameter TypeDescriptionDefault value
    username@PathExact username

    Examples

    +
    +

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    +

    GET http://example.org:9090/plugins/restapi/v1/users/testuser/vcard

    +
    +

    Add or update user’s vCard

    +

    Endpoint to add or replace a vCard of a particular user.

    +
    +

    PUT /users/{username}/vcard

    +
    +

    Payload: vCard XML data

    +

    Return value: HTTP status 200 (Created)

    +

    Possible parameters

    + + + + + + + + + + + + + + + + + + +
    ParameterParameter TypeDescriptionDefault value
    username@PathExact username

    Examples

    +
    +

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    +

    Header: Content-Type application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/users/testuser/vcard

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<rosterItem>
    - <jid>peter@pan.de</jid> <nickname>Peter Pan</nickname> <subscriptionType>0</subscriptionType> <groups> <group>Support</group> </groups></rosterItem>
    +<vCard xmlns="vcard-temp">  
    + <N> <FAMILY>Doe</FAMILY> <GIVEN>Janice</GIVEN> <MIDDLE>Francis</MIDDLE> </N> <ORG> <ORGNAME/> <ORGUNIT/> </ORG> <NICKNAME>Jane</NICKNAME> <FN>Janice Francis Doe</FN> <TITLE/> <URL/> <EMAIL> <HOME/> <INTERNET/> <PREF/> <USERID>j.doe@example.org</USERID> </EMAIL> <TEL> <WORK/> <VOICE/> <NUMBER/> </TEL> <TEL> <WORK/> <PAGER/> <NUMBER/> </TEL> <TEL> <WORK/> <FAX/> <NUMBER/> </TEL> <TEL> <WORK/> <CELL/> <NUMBER/> </TEL> <TEL> <HOME/> <VOICE/> <NUMBER/> </TEL> <TEL> <HOME/> <PAGER/> <NUMBER/> </TEL> <TEL> <HOME/> <FAX/> <NUMBER/> </TEL> <TEL> <HOME/> <CELL/> <NUMBER/> </TEL> <ADR> <WORK/> <LOCALITY/> <CTRY/> <STREET/> <PCODE/> <REGION/> </ADR> <ADR> <HOME/> <LOCALITY/> <CTRY/> <STREET/> <PCODE/> <REGION/> </ADR></vCard>  
     
    +

    Delete user’s vcard

    +

    Endpoint to remove the vCard of a particular user

    +
    +

    DELETE /users/{username}/vcard

    +
    +

    Payload: none

    +

    Return value: none

    +

    Possible parameters

    + + + + + + + + + + + + + + + + + + +
    ParameterParameter TypeDescriptionDefault value
    username@PathExact username

    Examples

    +
    +

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    +

    DELETE http://example.org:9090/plugins/restapi/v1/users/testuser/vcard

    +

    Chat room related REST Endpoints

    Retrieve all chat services

    Endpoint to get all chat services

    @@ -885,7 +958,7 @@

    Retrieve all chat services

    Payload: none

    Return value: Chat services

    Possible parameters: none

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/chatservices

    @@ -906,8 +979,8 @@

    XML Examples

    Payload Example (available parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<chatService>
    - <serviceName>new-chat-service-name</serviceName> <description>A mightily fine service</description> <hidden>false</hidden></chatService>
    +<chatService>  
    + <serviceName>new-chat-service-name</serviceName> <description>A mightily fine service</description> <hidden>false</hidden></chatService>  
     

    JSON Examples

    @@ -917,15 +990,16 @@

    JSON Examples

    Payload Example (available parameters):

    {
    - "serviceName": "new-chat-service-name", "description": "A mightily fine service", "hidden": false}
    + "serviceName": "new-chat-service-name", "description": "A mightily fine service", "hidden": false}  
     
    -

    Retrieve all chat rooms Endpoint to get all chat rooms

    +

    Retrieve all chat rooms

    +

    Endpoint to get all chat rooms

    GET /chatrooms

    Payload: none

    Return value: Chatrooms

    -

    Possible parameters

    +

    Possible parameters

    @@ -956,15 +1030,13 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/chatrooms
    - GET http://example.org:9090/plugins/restapi/v1/chatrooms?type=all
    - GET http://example.org:9090/plugins/restapi/v1/chatrooms?type=all&servicename=privateconf
    - GET http://example.org:9090/plugins/restapi/v1/chatrooms?search=test

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms

    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms?type=all

    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms?type=all&servicename=privateconf

    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms?search=test

    Retrieve a chat room

    Endpoint to get information over specific chat room

    @@ -973,7 +1045,7 @@

    Retrieve a chat room

    Payload: none

    Return value: Chatroom

    -

    Possible parameters

    +

    Possible parameters

    @@ -998,21 +1070,20 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/test
    - GET http://example.org:9090/plugins/restapi/v1/chatrooms/test?servicename=privateconf

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/test

    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/test?servicename=privateconf

    -

    Retrieve chat room participants Endpoint to get all participants with a role of specified room.

    +

    Retrieve chat room participants

    +

    Endpoint to get all participants with a role of specified room.

    GET /chatrooms/{roomName}/participants

    Payload: none

    Return value: Participants

    -

    Possible parameters

    +

    Possible parameters

    @@ -1037,12 +1108,10 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/room1/participants

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/room1/participants

    Retrieve chat room occupants

    Endpoint to get all occupants (all roles / affiliations) of a specified room.

    @@ -1051,7 +1120,7 @@

    Retrieve chat room occupants

    Payload: none

    Return value: Occupants

    -

    Possible parameters

    +

    Possible parameters

    @@ -1076,12 +1145,10 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/room1/occupants

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/chatrooms/room1/occupants

    Retrieve chat room message history

    Endpoint to get the chat message history of a specified room.

    @@ -1090,7 +1157,7 @@

    Retrieve chat room message history

    Payload: none

    Return value: Chat History

    -

    Possible parameters

    +

    Possible parameters

    @@ -1122,7 +1189,7 @@

    Possible parameters

    Payload: Chatroom

    Return value: HTTP status 201 (Created)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1150,40 +1217,36 @@

    Possible parameters

    XML Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/xml
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms

    -
    +

    Header: Content-Type: application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms

    Payload Example 1 (required parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<chatRoom>
    - <naturalName>global-1</naturalName> <roomName>global</roomName> <description>Global Chat Room</description></chatRoom>
    +<chatRoom>  
    + <naturalName>global-1</naturalName> <roomName>global</roomName> <description>Global Chat Room</description></chatRoom>  
     

    Payload Example 2 (available parameters):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<chatRoom>
    - <roomName>global</roomName> <naturalName>global-2</naturalName> <description>Global Chat Room</description> <subject>global-2 Subject</subject> <creationDate>2014-02-12T15:52:37.592+01:00</creationDate> <modificationDate>2014-09-12T15:35:54.702+02:00</modificationDate> <maxUsers>0</maxUsers> <persistent>true</persistent> <publicRoom>true</publicRoom> <registrationEnabled>false</registrationEnabled> <canAnyoneDiscoverJID>false</canAnyoneDiscoverJID> <canOccupantsChangeSubject>false</canOccupantsChangeSubject> <canOccupantsInvite>false</canOccupantsInvite> <canChangeNickname>false</canChangeNickname> <logEnabled>true</logEnabled> <loginRestrictedToNickname>false</loginRestrictedToNickname> <membersOnly>false</membersOnly> <moderated>false</moderated> <allowPM>anyone</allowPM> <broadcastPresenceRoles> <broadcastPresenceRole>moderator</broadcastPresenceRole> <broadcastPresenceRole>participant</broadcastPresenceRole> <broadcastPresenceRole>visitor</broadcastPresenceRole> </broadcastPresenceRoles> <owners> <owner>owner@localhost</owner> </owners> <admins> <admin>admin@localhost</admin> </admins> <members> <member>member2@localhost</member> <member>member1@localhost</member> </members> <outcasts> <outcast>outcast1@localhost</outcast> </outcasts></chatRoom>
    +<chatRoom>  
    + <roomName>global</roomName> <naturalName>global-2</naturalName> <description>Global Chat Room</description> <subject>global-2 Subject</subject> <creationDate>2014-02-12T15:52:37.592+01:00</creationDate> <modificationDate>2014-09-12T15:35:54.702+02:00</modificationDate> <maxUsers>0</maxUsers> <persistent>true</persistent> <publicRoom>true</publicRoom> <registrationEnabled>false</registrationEnabled> <canAnyoneDiscoverJID>false</canAnyoneDiscoverJID> <canOccupantsChangeSubject>false</canOccupantsChangeSubject> <canOccupantsInvite>false</canOccupantsInvite> <canChangeNickname>false</canChangeNickname> <logEnabled>true</logEnabled> <loginRestrictedToNickname>false</loginRestrictedToNickname> <membersOnly>false</membersOnly> <moderated>false</moderated> <allowPM>anyone</allowPM> <broadcastPresenceRoles> <broadcastPresenceRole>moderator</broadcastPresenceRole> <broadcastPresenceRole>participant</broadcastPresenceRole> <broadcastPresenceRole>visitor</broadcastPresenceRole> </broadcastPresenceRoles> <owners> <owner>owner@localhost</owner> </owners> <admins> <admin>admin@localhost</admin> </admins> <members> <member>member2@localhost</member> <member>member1@localhost</member> </members> <outcasts> <outcast>outcast1@localhost</outcast> </outcasts></chatRoom>  
     

    JSON Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/json
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms

    -
    +

    Header: Content-Type: application/json

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms

    Payload Example 1 (required parameters):

    {
    - "roomName": "global", "naturalName": "global-2", "description": "Global chat room"}
    + "roomName": "global", "naturalName": "global-2", "description": "Global chat room"}  
     

    Payload Example 2 (available parameters):

    {
    - "roomName": "global-1", "naturalName": "global-1_test_hello", "description": "Global chat room", "subject": "Global chat room subject", "creationDate": "2012-10-18T16:55:12.803+02:00", "modificationDate": "2014-07-10T09:49:12.411+02:00", "maxUsers": "0", "persistent": "true", "publicRoom": "true", "registrationEnabled": "false", "canAnyoneDiscoverJID": "true", "canOccupantsChangeSubject": "false", "canOccupantsInvite": "false", "canChangeNickname": "false", "logEnabled": "true", "loginRestrictedToNickname": "true", "membersOnly": "false", "moderated": "false", "allowPM": "anyone", "broadcastPresenceRoles": { "broadcastPresenceRole": [ "moderator", "participant", "visitor" ] }, "owners": { "owner": "owner@localhost" }, "admins": { "admin": [ "admin@localhost", "admin2@localhost" ] }, "members": { "member": [ "member@localhost", "member2@localhost" ] }, "outcasts": { "outcast": [ "outcast@localhost", "outcast2@localhost" ] }}
    + "roomName": "global-1", "naturalName": "global-1_test_hello", "description": "Global chat room", "subject": "Global chat room subject", "creationDate": "2012-10-18T16:55:12.803+02:00", "modificationDate": "2014-07-10T09:49:12.411+02:00", "maxUsers": "0", "persistent": "true", "publicRoom": "true", "registrationEnabled": "false", "canAnyoneDiscoverJID": "true", "canOccupantsChangeSubject": "false", "canOccupantsInvite": "false", "canChangeNickname": "false", "logEnabled": "true", "loginRestrictedToNickname": "true", "membersOnly": "false", "moderated": "false", "allowPM": "anyone", "broadcastPresenceRoles": { "broadcastPresenceRole": [ "moderator", "participant", "visitor" ] }, "owners": { "owner": "owner@localhost" }, "admins": { "admin": [ "admin@localhost", "admin2@localhost" ] }, "members": { "member": [ "member@localhost", "member2@localhost" ] }, "outcasts": { "outcast": [ "outcast@localhost", "outcast2@localhost" ] }}  
     

    REST API Version 1.3.0 and later - Payload Example 2 (available parameters):

    {
    - "roomName": "global-1", "naturalName": "global-1_test_hello", "description": "Global chat room", "subject": "Global chat room subject", "creationDate": "2012-10-18T16:55:12.803+02:00", "modificationDate": "2014-07-10T09:49:12.411+02:00", "maxUsers": "0", "persistent": "true", "publicRoom": "true", "registrationEnabled": "false", "canAnyoneDiscoverJID": "true", "canOccupantsChangeSubject": "false", "canOccupantsInvite": "false", "canChangeNickname": "false", "logEnabled": "true", "loginRestrictedToNickname": "true", "membersOnly": "false", "moderated": "false", "allowPM": "anyone", "broadcastPresenceRoles": [ "moderator", "participant", "visitor" ], "owners": [ "owner@localhost" ], "admins": [ "admin@localhost" ], "members": [ "member@localhost" ], "outcasts": [ "outcast@localhost" ]}
    + "roomName": "global-1", "naturalName": "global-1_test_hello", "description": "Global chat room", "subject": "Global chat room subject", "creationDate": "2012-10-18T16:55:12.803+02:00", "modificationDate": "2014-07-10T09:49:12.411+02:00", "maxUsers": "0", "persistent": "true", "publicRoom": "true", "registrationEnabled": "false", "canAnyoneDiscoverJID": "true", "canOccupantsChangeSubject": "false", "canOccupantsInvite": "false", "canChangeNickname": "false", "logEnabled": "true", "loginRestrictedToNickname": "true", "membersOnly": "false", "moderated": "false", "allowPM": "anyone", "broadcastPresenceRoles": [ "moderator", "participant", "visitor" ], "owners": [ "owner@localhost" ], "admins": [ "admin@localhost" ], "members": [ "member@localhost" ], "outcasts": [ "outcast@localhost" ]}  
     

    Create multiple chat room

    Endpoint to create multiple new chat rooms at once.

    @@ -1193,13 +1256,13 @@

    Create multiple chat room

    Payload: Chatrooms

    Return value: Result list, ordered by successes and failures

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<results>
    - <success> <result> <roomName>room1</roomName> <resultType>Success</resultType> <message>Room was successfully created</message> </result> <result> <roomName>room2</roomName> <resultType>Success</resultType> <message>Room was successfully created</message> </result> </success> <failure/> <other/></results>
    +<results>  
    + <success> <result> <roomName>room1</roomName> <resultType>Success</resultType> <message>Room was successfully created</message> </result> <result> <roomName>room2</roomName> <resultType>Success</resultType> <message>Room was successfully created</message> </result> </success> <failure/> <other/></results>  
     
    {
    - "success": [ { "roomName": "room1", "resultType": "Success", "message": "Room was successfully created" }, { "roomName": "room2", "resultType": "Success", "message": "Room was successfully created" } ], "failure": [], "other": []}
    + "success": [ { "roomName": "room1", "resultType": "Success", "message": "Room was successfully created" }, { "roomName": "room2", "resultType": "Success", "message": "Room was successfully created" } ], "failure": [], "other": []}  
     
    -

    Possible parameters

    +

    Possible parameters

    @@ -1232,8 +1295,8 @@

    Possible parameters

    Payload Example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<chatRooms>
    - <chatRoom> <roomName>room1</roomName> <description>description1</description> </chatRoom> <chatRoom> <roomName>room2</roomName> <description>description1</description> </chatRoom></chatRooms>
    +<chatRooms>  
    + <chatRoom> <roomName>room1</roomName> <description>description1</description> </chatRoom> <chatRoom> <roomName>room2</roomName> <description>description1</description> </chatRoom></chatRooms>  
     

    For more examples, with more parameters, see the create a chat room endpoint.

    JSON Examples

    @@ -1244,16 +1307,17 @@

    JSON Examples

    Payload Example 1 (required parameters):

    {
    - "chatRooms": [ { "roomName": "room1", "description": "description1" }, { "roomName": "room2", "description": "description2" } ]}
    + "chatRooms": [ { "roomName": "room1", "description": "description1" }, { "roomName": "room2", "description": "description2" } ]}  
     

    For more examples, with more parameters, see the create a chat room endpoint.

    -

    Delete a chat room Endpoint to delete a chat room.

    +

    Delete a chat room

    +

    Endpoint to delete a chat room.

    DELETE /chatrooms/{roomName}

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1278,21 +1342,20 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/testroom
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/testroom?servicename=privateconf

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/testroom

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/testroom?servicename=privateconf

    -

    Update a chat room Endpoint to update a chat room.

    +

    Update a chat room

    +

    Endpoint to update a chat room.

    PUT /chatrooms/{roomName}

    Payload: Chatroom

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1323,35 +1386,31 @@

    Possible parameters

    -
    false

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/chatrooms/global

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/chatrooms/global

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<chatRoom>
    - <roomName>global</roomName> <naturalName>global-2</naturalName> <description>Global Chat Room edit</description> <subject>New subject</subject> <password>test</password> <creationDate>2014-02-12T15:52:37.592+01:00</creationDate> <modificationDate>2014-09-12T14:20:56.286+02:00</modificationDate> <maxUsers>0</maxUsers> <persistent>true</persistent> <publicRoom>true</publicRoom> <registrationEnabled>false</registrationEnabled> <canAnyoneDiscoverJID>false</canAnyoneDiscoverJID> <canOccupantsChangeSubject>false</canOccupantsChangeSubject> <canOccupantsInvite>false</canOccupantsInvite> <canChangeNickname>false</canChangeNickname> <logEnabled>true</logEnabled> <loginRestrictedToNickname>false</loginRestrictedToNickname> <membersOnly>false</membersOnly> <moderated>false</moderated> <allowPM>anyone</allowPM> <broadcastPresenceRoles/> <owners> <owner>owner@localhost</owner> </owners> <admins> <admin>admin@localhost</admin> </admins> <members> <member>member2@localhost</member> <member>member1@localhost</member> </members> <outcasts> <outcast>outcast1@localhost</outcast> </outcasts></chatRoom>
    +<chatRoom>  
    + <roomName>global</roomName> <naturalName>global-2</naturalName> <description>Global Chat Room edit</description> <subject>New subject</subject> <password>test</password> <creationDate>2014-02-12T15:52:37.592+01:00</creationDate> <modificationDate>2014-09-12T14:20:56.286+02:00</modificationDate> <maxUsers>0</maxUsers> <persistent>true</persistent> <publicRoom>true</publicRoom> <registrationEnabled>false</registrationEnabled> <canAnyoneDiscoverJID>false</canAnyoneDiscoverJID> <canOccupantsChangeSubject>false</canOccupantsChangeSubject> <canOccupantsInvite>false</canOccupantsInvite> <canChangeNickname>false</canChangeNickname> <logEnabled>true</logEnabled> <loginRestrictedToNickname>false</loginRestrictedToNickname> <membersOnly>false</membersOnly> <moderated>false</moderated> <allowPM>anyone</allowPM> <broadcastPresenceRoles/> <owners> <owner>owner@localhost</owner> </owners> <admins> <admin>admin@localhost</admin> </admins> <members> <member>member2@localhost</member> <member>member1@localhost</member> </members> <outcasts> <outcast>outcast1@localhost</outcast> </outcasts></chatRoom>  
     

    Invite user or user group to a chat Room

    Endpoint to invite a user or a user group to a room.

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/xml
    - POST http://localhost:9090/plugins/restapi/v1/chatrooms/{roomName}/invite/{name}

    -
    +

    Header: Content-Type: application/xml

    +

    POST http://localhost:9090/plugins/restapi/v1/chatrooms/{roomName}/invite/{name}

    Payload Example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<mucInvitation>
    - <reason>Hello, come to this room, it is nice</reason></mucInvitation>
    +<mucInvitation>  
    + <reason>Hello, come to this room, it is nice</reason></mucInvitation>  
     

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1385,11 +1444,11 @@

    Possible parameters

    Payload Example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<mucInvitation>
    - <reason>Hello, come to this room, it is nice</reason> <jidsToInvite> <jid>jane@example.org</jid> <jid>ADNMQP8=@example.org/695c6ae413c00446733d926ccadefd8b</jid> <jid>john</jid> <jid>SomeGroupName</jid> </jidsToInvite></mucInvitation>
    +<mucInvitation>  
    + <reason>Hello, come to this room, it is nice</reason> <jidsToInvite> <jid>jane@example.org</jid> <jid>ADNMQP8=@example.org/695c6ae413c00446733d926ccadefd8b</jid> <jid>john</jid> <jid>SomeGroupName</jid> </jidsToInvite></mucInvitation>  
     

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1415,7 +1474,7 @@

    Possible parameters

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1446,7 +1505,7 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    Header: Content-Type application/xml

    @@ -1454,8 +1513,8 @@

    Possible parameters

    Return payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<members>
    - <member>member2@localhost</member> <member>member1@localhost</member></members>
    +<members>  
    + <member>member2@localhost</member> <member>member1@localhost</member></members>  
     

    Add user with affiliation to chat room

    Endpoint to add a new user with affiliation to a room.

    @@ -1464,7 +1523,7 @@

    Add user with affiliation to cha

    Payload: none

    Return value: HTTP status 201 (Created)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1507,18 +1566,16 @@

    Possible parameters

    -
    false

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser@openfire.com
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/testUser
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/testUser?sendInvitations=true
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/testUser
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser?servicename=privateconf

    -
    +

    Header: Content-Type application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser@openfire.com

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/testUser

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/testUser?sendInvitations=true

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/testUser

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser?servicename=privateconf

    Replace all users with a affiliation in a chat room

    Endpoint to replace all users with a particular affiliation in a multi-user chat room. Note that a user can only have one type of affiliation with a room. By adding a user using a particular affiliation, any other pre-existing affiliation is removed.

    @@ -1527,7 +1584,7 @@

    Replace all users w

    Payload: list of affiliations

    Return value: HTTP status 201 (Created)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1564,7 +1621,7 @@

    Possible parameters

    -
    false

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    Header: Content-Type application/xml

    @@ -1572,8 +1629,8 @@

    Possible parameters

    Request Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<members>
    - <member>member2@localhost</member> <member>member1@localhost</member></members>
    +<members>  
    + <member>member2@localhost</member> <member>member1@localhost</member></members>  
     

    Add multiple users with a affiliation to a chat room

    Endpoint to add multiple users with an affiliation to a multi-user chat room. Note that a user can only have one type of affiliation with a room. By adding a user using a particular affiliation, any other pre-existing affiliation is removed.

    @@ -1582,7 +1639,7 @@

    Add multiple users

    Payload: list of affiliations

    Return value: HTTP status 201 (Created)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1619,7 +1676,7 @@

    Possible parameters

    -
    false

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    Header: Content-Type application/xml

    @@ -1627,8 +1684,8 @@

    Possible parameters

    Request Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<members>
    - <member>member2@localhost</member> <member>member1@localhost</member></members>
    +<members>  
    + <member>member2@localhost</member> <member>member1@localhost</member></members>  
     

    Add group with affiliation to chat room

    Endpoint to add a new group with affiliation to a room.

    @@ -1637,7 +1694,7 @@

    Add group with affiliation to c

    Payload: none

    Return value: HTTP status 201 (Created)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1680,27 +1737,24 @@

    Possible parameters

    -
    false

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml

    -
    +

    Header: Content-Type application/xml

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/group/testGroup

    -
    -

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/group/testGroup
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/group/testGroup
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/group/testGroup
    - POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/group/testUser?servicename=privateconf

    -
    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/group/testGroup

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/group/testGroup

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/group/testGroup

    +

    POST http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/group/testUser?servicename=privateconf

    -

    Delete a user from a chat room Endpoint to remove a room user affiliation.

    +

    Delete a user from a chat room

    +

    Endpoint to remove a room user affiliation.

    DELETE /chatrooms/{roomName}/{affiliations}/{name}

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1737,40 +1791,38 @@

    Possible parameters

    -
    conference

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser@openfire.com
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/testUser
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/testUser
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/testUser
    - DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser?servicename=privateconf

    -
    +

    Header: Content-Type application/xml

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser@openfire.com

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/admins/testUser

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/members/testUser

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/outcasts/testUser

    +

    DELETE http://example.org:9090/plugins/restapi/v1/chatrooms/global/owners/testUser?servicename=privateconf

    System related REST Endpoints

    -

    Retrieve all system properties Endpoint to get all system properties

    +

    Retrieve all system properties

    +

    Endpoint to get all system properties

    GET /system/properties

    Payload: none

    Return value: System properties

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/system/properties

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/system/properties

    -

    Retrieve system property Endpoint to get information over specific system property

    +

    Retrieve system property

    +

    Endpoint to get information over specific system property

    GET /system/properties/{propertyName}

    Payload: none

    Return value: System property

    -

    Possible parameters

    +

    Possible parameters

    @@ -1789,28 +1841,27 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/system/properties/xmpp.domain

    -

    Create a system property Endpoint to create a system property

    +

    Create a system property

    +

    Endpoint to create a system property

    POST system/properties

    Payload: System Property

    Return value: HTTP status 201 (Created)

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/xml
    - POST http://example.org:9090/plugins/restapi/v1/system/properties

    -
    +

    Header: Content-Type: application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/system/properties

    Payload Example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<property key="propertyName" value="propertyValue"/>
    +<property key="propertyName" value="propertyValue"/>  
     

    Delete a system property

    Endpoint to delete a system property

    @@ -1819,7 +1870,7 @@

    Delete a system property

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1838,12 +1889,10 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/system/properties/propertyName

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/system/properties/propertyName

    Update a system property

    Endpoint to update / overwrite a system property

    @@ -1852,7 +1901,7 @@

    Update a system property

    Payload: System property

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -1871,17 +1920,15 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/system/properties/propertyName

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/system/properties/propertyName

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<property key="propertyName" value="anotherValue"/>
    +<property key="propertyName" value="anotherValue"/>  
     

    Retrieve concurrent sessions

    Endpoint to get count of concurrent sessions

    @@ -1890,7 +1937,7 @@

    Retrieve concurrent sessions

    Payload: none

    Return value: Sessions count

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/system/statistics/sessions

    @@ -1951,7 +1998,7 @@

    Perform ‘connections’ readiness

    Payload: none

    Return value: HTTP status 200 (OK). Any HTTP status outside the range 200-399 indicates failure.

    -

    Possible parameters

    +

    Possible parameters

    @@ -1977,26 +2024,26 @@

    Possible parameters

    Group related REST Endpoints

    -

    Retrieve all groups Endpoint to get all groups

    +

    Retrieve all groups

    +

    Endpoint to get all groups

    GET /groups

    Payload: none

    Return value: Groups

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/groups

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/groups

    -

    Retrieve a group Endpoint to get information over specific group

    +

    Retrieve a group

    +

    Endpoint to get information over specific group

    GET /groups/{groupName}

    Payload: none

    Return value: Group

    -

    Possible parameters

    +

    Possible parameters

    @@ -2015,29 +2062,28 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/groups/moderators

    -

    Create a group Endpoint to create a new group

    +

    Create a group

    +

    Endpoint to create a new group

    POST /groups

    Payload: Group

    Return value: HTTP status 201 (Created)

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type: application/xml
    - POST http://example.org:9090/plugins/restapi/v1/groups

    -
    +

    Header: Content-Type: application/xml

    +

    POST http://example.org:9090/plugins/restapi/v1/groups

    Payload Example:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<group>
    - <name>GroupName</name> <description>Some description</description> <isshared>false</isshared></group>
    +<group>  
    + <name>GroupName</name> <description>Some description</description> <isshared>false</isshared></group>  
     

    Delete a group

    Endpoint to delete a group

    @@ -2046,7 +2092,7 @@

    Delete a group

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -2065,12 +2111,10 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    DELETE http://example.org:9090/plugins/restapi/v1/groups/groupToDelete

    -
    +

    DELETE http://example.org:9090/plugins/restapi/v1/groups/groupToDelete

    Update a group

    Endpoint to update / overwrite a group

    @@ -2079,7 +2123,7 @@

    Update a group

    Payload: Group

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -2098,18 +2142,16 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    Header: Content-Type application/xml
    - PUT http://example.org:9090/plugins/restapi/v1/groups/groupNameToUpdate

    -
    +

    Header: Content-Type application/xml

    +

    PUT http://example.org:9090/plugins/restapi/v1/groups/groupNameToUpdate

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<group>
    - <name>groupNameToUpdate</name> <description>New description</description> <isshared>false</isshared></group>
    +<group>  
    + <name>groupNameToUpdate</name> <description>New description</description> <isshared>false</isshared></group>  
     

    Session related REST Endpoints

    Retrieve all user session

    @@ -2119,12 +2161,10 @@

    Retrieve all user session

    Payload: none

    Return value: Sessions

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/sessions

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/sessions

    Retrieve the user sessions

    Endpoint to get sessions from a user

    @@ -2133,7 +2173,7 @@

    Retrieve the user sessions

    Payload: none

    Return value: Sessions

    -

    Possible parameters

    +

    Possible parameters

    @@ -2152,7 +2192,7 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/sessions/testuser

    @@ -2164,7 +2204,7 @@

    Close all user sessions

    Payload: none

    Return value: HTTP status 200 (OK)

    -

    Possible parameters

    +

    Possible parameters

    @@ -2183,7 +2223,7 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    DELETE http://example.org:9090/plugins/restapi/v1/sessions/testuser

    @@ -2196,17 +2236,15 @@

    Send a broadcast message

    Payload: Message

    Return value: HTTP status 201 (Created)

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    POST http://example.org:9090/plugins/restapi/v1/messages/users

    -
    +

    POST http://example.org:9090/plugins/restapi/v1/messages/users

    Payload:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    -<message>
    - <body>Your message</body></message>
    +<message>  
    + <body>Your message</body></message>  
     

    Security Audit related REST Endpoints

    Retrieve the Security audit logs

    @@ -2216,7 +2254,7 @@

    Retrieve the Security audit logs

    Payload: none

    Return value: Security Audit Logs

    -

    Possible parameters

    +

    Possible parameters

    @@ -2259,12 +2297,10 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    -
    -

    GET http://example.org:9090/plugins/restapi/v1/logs/security

    -
    +

    GET http://example.org:9090/plugins/restapi/v1/logs/security

    Clustering related REST Endpoints

    Retrieve information for all cluster nodes.

    @@ -2275,7 +2311,7 @@

    Retrieve information for al

    Payload: none

    Return value: ClusterNodes

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/clustering/nodes

    @@ -2288,7 +2324,7 @@

    Retrieve information

    Payload: none

    Return value: ClusterNode

    -

    Possible parameters

    +

    Possible parameters

    @@ -2307,7 +2343,7 @@

    Possible parameters

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/clustering/nodes/52a89928-66f7-45fd-9bb8-096de07400ac

    @@ -2319,7 +2355,7 @@

    Retrieve the Clustering status

    Payload: none

    Return value: String describing the clustering status of this Openfire instance

    -

    Examples

    +

    Examples

    Header: Authorization: Basic YWRtaW46MTIzNDU=

    GET http://example.org:9090/plugins/restapi/v1/clustering/status

    @@ -2827,15 +2863,15 @@

    Configuration

    Using the Plugin

    To administer users, submit HTTP requests to the userservice service. The service address is [hostname]plugins/restapi/userservice. For example, if your server name is “example.com”, the URL is http://example.com/plugins/restapi/userservice

    The following parameters can be passed into the request:

    -

    | Name | | Description | |--------------|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    - | type | Required | The admin service required. Possible values are ‘add’, ‘delete’, ‘update’, ‘enable’, ‘disable’, ‘add_roster’, ‘update_roster’, ‘delete_roster’, ‘grouplist’, ‘usergrouplist’. |
    - | secret | Required | The secret key that allows access to the User Service. |
    - | username | Required | The username of the user to ‘add’, ‘delete’, ‘update’, ‘enable’, ‘disable’, ‘add_roster’, ‘update_roster’, ‘delete_roster’. ie the part before the @ symbol. |
    - | password | Required for ‘add’ operation | The password of the new user or the user being updated. |
    - | name | Optional | The display name of the new user or the user being updated. For ‘add_roster’, ‘update_roster’ operations specifies the nickname of the roster item. |
    - | email | Optional | The email address of the new user or the user being updated. |
    - | groups | Optional | List of groups where the user is a member. Values are comma delimited. When used with types “add” or “update”, it adds the user to shared groups and auto-creates new groups. When used with ‘add_roster’ and ‘update_roster’, it adds the user to roster groups provided the group name does not clash with an existing shared group. |
    - | item_jid | Required for ‘add_roster’, ‘update_roster’, ‘delete_roster’ operations. | The JID of the roster item |
    +

    | Name | | Description | |--------------|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
    + | type | Required | The admin service required. Possible values are ‘add’, ‘delete’, ‘update’, ‘enable’, ‘disable’, ‘add_roster’, ‘update_roster’, ‘delete_roster’, ‘grouplist’, ‘usergrouplist’. |
    + | secret | Required | The secret key that allows access to the User Service. |
    + | username | Required | The username of the user to ‘add’, ‘delete’, ‘update’, ‘enable’, ‘disable’, ‘add_roster’, ‘update_roster’, ‘delete_roster’. ie the part before the @ symbol. |
    + | password | Required for ‘add’ operation | The password of the new user or the user being updated. |
    + | name | Optional | The display name of the new user or the user being updated. For ‘add_roster’, ‘update_roster’ operations specifies the nickname of the roster item. |
    + | email | Optional | The email address of the new user or the user being updated. |
    + | groups | Optional | List of groups where the user is a member. Values are comma delimited. When used with types “add” or “update”, it adds the user to shared groups and auto-creates new groups. When used with ‘add_roster’ and ‘update_roster’, it adds the user to roster groups provided the group name does not clash with an existing shared group. |
    + | item_jid | Required for ‘add_roster’, ‘update_roster’, ‘delete_roster’ operations. | The JID of the roster item |
    | subscription | Optional | Type of subscription for ‘add_roster’, ‘update_roster’ operations. Possible numeric values are: -1(remove), 0(none), 1(to), 2(from), 3(both). |

    Sample HTML

    The following example adds a user

    @@ -2862,13 +2898,13 @@

    Sample HTML

    http://example.com:9090/plugins/restapi/userservice?type=grouplist&secret=bigsecret
    Which replies an XML group list formatted like this:

    <result>
    - <groupname>group1</groupname> <groupname>group2</groupname></result>
    + <groupname>group1</groupname> <groupname>group2</groupname></result>  
     

    The following example gets all groups for a specific user

    http://example.com:9090/plugins/restapi/userservice?type=usergrouplist&secret=bigsecret&username=kafka
    Which replies an XML group list formatted like this:

    <result>
    - <groupname>usergroup1</groupname> <groupname>usergroup2</groupname></result>
    + <groupname>usergroup1</groupname> <groupname>usergroup2</groupname></result>  
     

    When sending double characters (Chinese/Japanese/Korean etc.) you should URLEncode the string as utf8.
    In Java this is done like this

    diff --git a/readme.md b/readme.md index a07b0e832..a2d8e9447 100644 --- a/readme.md +++ b/readme.md @@ -626,6 +626,148 @@ Endpoint to update a roster entry ``` +## Retrieve user's vcard +Endpoint to get the vCard of a particular user +> **GET** /users/{username}/vcard + +**Payload:** none + +**Return value:** vCard XML data + +### Possible parameters + +| Parameter | Parameter Type | Description | Default value | +|-----------|-----------------|----------------|---------------| +| username | @Path | Exact username | | + +### Examples +>**Header:** Authorization: Basic YWRtaW46MTIzNDU= +> +>**GET** http://example.org:9090/plugins/restapi/v1/users/testuser/vcard + +## Add or update user's vCard +Endpoint to add or replace a vCard of a particular user. +> **PUT** /users/{username}/vcard + +**Payload:** vCard XML data + +**Return value:** HTTP status 200 (Created) + +### Possible parameters + + +| Parameter | Parameter Type | Description | Default value | +|-----------|-----------------|----------------|---------------| +| username | @Path | Exact username | | + +### Examples +>**Header:** Authorization: Basic YWRtaW46MTIzNDU= +> +>**Header:** Content-Type application/xml +> +>**POST** http://example.org:9090/plugins/restapi/v1/users/testuser/vcard + +**Payload:** +```xml + + + + Doe + Janice + Francis + + + + + + Jane + Janice Francis Doe + + <URL/> + <EMAIL> + <HOME/> + <INTERNET/> + <PREF/> + <USERID>j.doe@example.org</USERID> + </EMAIL> + <TEL> + <WORK/> + <VOICE/> + <NUMBER/> + </TEL> + <TEL> + <WORK/> + <PAGER/> + <NUMBER/> + </TEL> + <TEL> + <WORK/> + <FAX/> + <NUMBER/> + </TEL> + <TEL> + <WORK/> + <CELL/> + <NUMBER/> + </TEL> + <TEL> + <HOME/> + <VOICE/> + <NUMBER/> + </TEL> + <TEL> + <HOME/> + <PAGER/> + <NUMBER/> + </TEL> + <TEL> + <HOME/> + <FAX/> + <NUMBER/> + </TEL> + <TEL> + <HOME/> + <CELL/> + <NUMBER/> + </TEL> + <ADR> + <WORK/> + <LOCALITY/> + <CTRY/> + <STREET/> + <PCODE/> + <REGION/> + </ADR> + <ADR> + <HOME/> + <LOCALITY/> + <CTRY/> + <STREET/> + <PCODE/> + <REGION/> + </ADR> +</vCard> +``` + +## Delete user's vcard +Endpoint to remove the vCard of a particular user +> **DELETE** /users/{username}/vcard + +**Payload:** none + +**Return value:** none + +### Possible parameters + +| Parameter | Parameter Type | Description | Default value | +|-----------|-----------------|----------------|---------------| +| username | @Path | Exact username | | + +### Examples +>**Header:** Authorization: Basic YWRtaW46MTIzNDU= +> +>**DELETE** http://example.org:9090/plugins/restapi/v1/users/testuser/vcard + # Chat room related REST Endpoints ## Retrieve all chat services diff --git a/src/java/org/jivesoftware/openfire/plugin/rest/controller/UserServiceController.java b/src/java/org/jivesoftware/openfire/plugin/rest/controller/UserServiceController.java index c7bde3825..54fd6a239 100644 --- a/src/java/org/jivesoftware/openfire/plugin/rest/controller/UserServiceController.java +++ b/src/java/org/jivesoftware/openfire/plugin/rest/controller/UserServiceController.java @@ -16,6 +16,10 @@ package org.jivesoftware.openfire.plugin.rest.controller; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; import org.jivesoftware.openfire.SessionManager; import org.jivesoftware.openfire.SharedGroupException; import org.jivesoftware.openfire.XMPPServer; @@ -37,6 +41,7 @@ import org.jivesoftware.openfire.user.UserAlreadyExistsException; import org.jivesoftware.openfire.user.UserManager; import org.jivesoftware.openfire.user.UserNotFoundException; +import org.jivesoftware.openfire.vcard.VCardManager; import org.jivesoftware.util.JiveGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,6 +74,8 @@ public class UserServiceController { /** The lock out manager. */ private final LockOutManager lockOutManager; + private final VCardManager vcardManager; + /** * Gets the single instance of UserServiceController. * @@ -98,6 +105,7 @@ private UserServiceController() { userManager = server.getUserManager(); rosterManager = server.getRosterManager(); lockOutManager = server.getLockOutManager(); + vcardManager = server.getVCardManager(); } public static void log(String logMessage) { @@ -611,4 +619,82 @@ private Roster getUserRoster(String username) throws ServiceException { Response.Status.NOT_FOUND, e); } } + + /** + * Retrieves a vCard for a user. + * + * @param username The username for which to return a vcard + * @return A vCard (or null) + */ + public Element getUserVCard(String username) throws ServiceException + { + log("Get user vCard for user: " + username); + if (username.contains("@")) { + final JID jid = new JID(username); + if (jid.getDomain().equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { + username = jid.getNode(); + } else { + // Implementing this would require us to iterate over all groups, which is a performance nightmare. + throw new ServiceException("This service cannot be used for non-local users.", username, ExceptionType.USER_NOT_FOUND_EXCEPTION, Response.Status.INTERNAL_SERVER_ERROR); + } + } + + return vcardManager.getVCard(username); + } + + /** + * Adds or updates a vCard for a user. + * + * @param username The username for which to return a vcard + * @param data The raw XML vCard data + */ + public void setUserVCard(String username, String data) throws ServiceException + { + log("Set user vCard for user: " + username); + if (username.contains("@")) { + final JID jid = new JID(username); + if (jid.getDomain().equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { + username = jid.getNode(); + } else { + // Implementing this would require us to iterate over all groups, which is a performance nightmare. + throw new ServiceException("This service cannot be used for non-local users.", username, ExceptionType.USER_NOT_FOUND_EXCEPTION, Response.Status.INTERNAL_SERVER_ERROR); + } + } + + try { + final Document document = DocumentHelper.parseText(data); + vcardManager.setVCard(username, document.getRootElement()); + } catch (DocumentException e) { + throw new ServiceException("Could not parse the provided data as a vCard", username, ExceptionType.ILLEGAL_ARGUMENT_EXCEPTION, Response.Status.BAD_REQUEST); + } catch (UnsupportedOperationException e) { + throw new ServiceException("Cannot update vCards in the system, as the vCard system is configured to be read-only.", username, ExceptionType.ILLEGAL_ARGUMENT_EXCEPTION, Response.Status.CONFLICT); + } catch (Exception e) { + throw new ServiceException("Unexpected problem while trying to update vCard.", username, ExceptionType.ILLEGAL_ARGUMENT_EXCEPTION, Response.Status.INTERNAL_SERVER_ERROR); + } + } + + /** + * Removes a vCard for a user. + * + * @param username The username for which to return a vcard + */ + public void deleteUserVCard(String username) throws ServiceException + { + log("Get user vCard for user: " + username); + if (username.contains("@")) { + final JID jid = new JID(username); + if (jid.getDomain().equals(XMPPServer.getInstance().getServerInfo().getXMPPDomain())) { + username = jid.getNode(); + } else { + // Implementing this would require us to iterate over all groups, which is a performance nightmare. + throw new ServiceException("This service cannot be used for non-local users.", username, ExceptionType.USER_NOT_FOUND_EXCEPTION, Response.Status.INTERNAL_SERVER_ERROR); + } + } + + try { + vcardManager.deleteVCard(username); + } catch (UnsupportedOperationException e) { + throw new ServiceException("Cannot update vCards in the system, as the vCard system is configured to be read-only.", username, ExceptionType.ILLEGAL_ARGUMENT_EXCEPTION, Response.Status.CONFLICT); + } + } } diff --git a/src/java/org/jivesoftware/openfire/plugin/rest/service/JerseyWrapper.java b/src/java/org/jivesoftware/openfire/plugin/rest/service/JerseyWrapper.java index c61174eb3..1fa6a3314 100644 --- a/src/java/org/jivesoftware/openfire/plugin/rest/service/JerseyWrapper.java +++ b/src/java/org/jivesoftware/openfire/plugin/rest/service/JerseyWrapper.java @@ -115,7 +115,8 @@ public JerseyWrapper(@Context ServletConfig servletConfig) { UserLockoutService.class, UserRosterService.class, UserService.class, - UserServiceLegacy.class + UserServiceLegacy.class, + UserVCardService.class ); // Exception mapper diff --git a/src/java/org/jivesoftware/openfire/plugin/rest/service/UserVCardService.java b/src/java/org/jivesoftware/openfire/plugin/rest/service/UserVCardService.java new file mode 100644 index 000000000..c3ca53926 --- /dev/null +++ b/src/java/org/jivesoftware/openfire/plugin/rest/service/UserVCardService.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 Ignite Realtime Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jivesoftware.openfire.plugin.rest.service; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.parameters.RequestBody; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.dom4j.Element; +import org.jivesoftware.openfire.SharedGroupException; +import org.jivesoftware.openfire.plugin.rest.controller.UserServiceController; +import org.jivesoftware.openfire.plugin.rest.entity.RosterItemEntity; +import org.jivesoftware.openfire.plugin.rest.entity.UserGroupsEntity; +import org.jivesoftware.openfire.plugin.rest.exceptions.ExceptionType; +import org.jivesoftware.openfire.plugin.rest.exceptions.ServiceException; +import org.jivesoftware.openfire.user.UserAlreadyExistsException; +import org.jivesoftware.openfire.user.UserNotFoundException; + +import javax.annotation.PostConstruct; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("restapi/v1/users/{username}/vcard") +@Tag(name = "Users", description = "Managing vCards of Openfire users.") +public class UserVCardService +{ + private UserServiceController plugin; + + @PostConstruct + public void init() { + plugin = UserServiceController.getInstance(); + } + + @GET + @Operation( summary = "Get user's vCard", + description = "Retrieves the vCard for a particular user.", + responses = { + @ApiResponse(responseCode = "200", description = "The vCard of the user"), + @ApiResponse(responseCode = "204", description = "No vCard found.") + }) + @Produces({MediaType.APPLICATION_XML}) + public String getUserVcard( + @Parameter(description = "The username for user for which to return the vcard.", required = true) @PathParam("username") String username) + throws ServiceException + { + final Element el = plugin.getUserVCard(username); + if (el == null) { + return null; + } + return el.asXML(); + } + + @PUT + @Operation( summary = "Update vCard", + description = "Creates or changes a vCard of a particular user.", + responses = { + @ApiResponse(responseCode = "200", description = "The vCard was updated/created."), + @ApiResponse(responseCode = "400", description = "Provided data could not be parsed."), + @ApiResponse(responseCode = "409", description = "Cannot change vCard, as Openfire is configured to have read-only vCards.") + }) + @Consumes({MediaType.APPLICATION_XML}) + public Response setUserVcard( + @Parameter(description = "The username of the user for which the update a roster entry.", required = true) @PathParam("username") String username, + @RequestBody(description = "The updated definition of the vCard.", required = true) String vCard) + throws ServiceException + { + plugin.setUserVCard(username, vCard); + return Response.status(Response.Status.OK).build(); + } + + @DELETE + @Operation( summary = "Delete vCard", + description = "Removes a vCard of a particular user.", + responses = { + @ApiResponse(responseCode = "200", description = "The vCard was deleted."), + @ApiResponse(responseCode = "409", description = "Cannot delete vCard, as Openfire is configured to have read-only vCards.") + }) + public Response deleteUserVcard( + @Parameter(description = "The username of the user for which the update a roster entry.", required = true) @PathParam("username") String username) + throws ServiceException + { + plugin.deleteUserVCard(username); + return Response.status(Response.Status.OK).build(); + } +}