Commit 5fd155543f3d8e9ea88f27bc1a97b82a62275b06

Authored by Andrii Shvaika
1 parent 91d614ba

User controller

... ... @@ -181,9 +181,9 @@ public abstract class BaseController {
181 181 public static final String RULE_CHAIN_ID_PARAM_DESCRIPTION = "A string value representing the rule chain id. For example, '784f394c-42b6-435a-983c-b7beff2784f9'";
182 182
183 183 protected static final String SYSTEM_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' authority.";
184   - protected static final String SYSTEM_AND_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";
  184 + protected static final String SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'SYS_ADMIN' or 'TENANT_ADMIN' authority.";
185 185 protected static final String TENANT_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' authority.";
186   - protected static final String TENANT_AND_USER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";
  186 + protected static final String TENANT_OR_USER_AUTHORITY_PARAGRAPH = "\n\nAvailable for users with 'TENANT_ADMIN' or 'CUSTOMER_USER' authority.";
187 187
188 188 protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page";
189 189 protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0";
... ... @@ -196,6 +196,7 @@ public abstract class BaseController {
196 196 protected static final String DASHBOARD_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the dashboard title.";
197 197 protected static final String RPC_TEXT_SEARCH_DESCRIPTION = "Not implemented. Leave empty.";
198 198 protected static final String DEVICE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the device name.";
  199 + protected static final String USER_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the user email.";
199 200 protected static final String TENANT_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant name.";
200 201 protected static final String TENANT_PROFILE_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the tenant profile name.";
201 202 protected static final String RULE_CHAIN_TEXT_SEARCH_DESCRIPTION = "The case insensitive 'startsWith' filter based on the rule chain name.";
... ... @@ -209,6 +210,7 @@ public abstract class BaseController {
209 210 protected static final String CUSTOMER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, city";
210 211 protected static final String RPC_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, expirationTime, request, response";
211 212 protected static final String DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, deviceProfileName, label, customerTitle";
  213 + protected static final String USER_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, firstName, lastName, email";
212 214 protected static final String TENANT_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, title, email, country, state, city, address, address2, zip, phone, email";
213 215 protected static final String TENANT_PROFILE_SORT_PROPERTY_ALLOWABLE_VALUES = "createdTime, name, description, isDefault";
214 216 protected static final String TENANT_PROFILE_INFO_SORT_PROPERTY_ALLOWABLE_VALUES = "id, name";
... ...
... ... @@ -103,8 +103,8 @@ public class DeviceController extends BaseController {
103 103
104 104 @ApiOperation(value = "Get Device (getDeviceById)",
105 105 notes = "Fetch the Device object based on the provided Device Id. " +
106   - "If the user has the authority of 'Tenant Administrator', the server checks that the device is owned by the same tenant. " +
107   - "If the user has the authority of 'Customer User', the server checks that the device is assigned to the same customer.")
  106 + "If the user has the authority of 'TENANT_ADMIN', the server checks that the device is owned by the same tenant. " +
  107 + "If the user has the authority of 'CUSTOMER_USER', the server checks that the device is assigned to the same customer.")
108 108 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
109 109 @RequestMapping(value = "/device/{deviceId}", method = RequestMethod.GET)
110 110 @ResponseBody
... ...
... ... @@ -81,7 +81,7 @@ public class DeviceProfileController extends BaseController {
81 81
82 82 @ApiOperation(value = "Get Device Profile Info (getDeviceProfileInfoById)",
83 83 notes = "Fetch the Device Profile Info object based on the provided Device Profile Id. "
84   - + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_AND_USER_AUTHORITY_PARAGRAPH,
  84 + + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH,
85 85 produces = "application/json")
86 86 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
87 87 @RequestMapping(value = "/deviceProfileInfo/{deviceProfileId}", method = RequestMethod.GET)
... ... @@ -100,7 +100,7 @@ public class DeviceProfileController extends BaseController {
100 100
101 101 @ApiOperation(value = "Get Default Device Profile (getDefaultDeviceProfileInfo)",
102 102 notes = "Fetch the Default Device Profile Info object. " +
103   - DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_AND_USER_AUTHORITY_PARAGRAPH,
  103 + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH,
104 104 produces = "application/json")
105 105 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
106 106 @RequestMapping(value = "/deviceProfileInfo/default", method = RequestMethod.GET)
... ... @@ -321,7 +321,7 @@ public class DeviceProfileController extends BaseController {
321 321
322 322 @ApiOperation(value = "Get Device Profiles for transport type (getDeviceProfileInfos)",
323 323 notes = "Returns a page of devices profile info objects owned by tenant. " +
324   - PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_AND_USER_AUTHORITY_PARAGRAPH,
  324 + PAGE_DATA_PARAMETERS + DEVICE_PROFILE_INFO_DESCRIPTION + TENANT_OR_USER_AUTHORITY_PARAGRAPH,
325 325 produces = "application/json")
326 326 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
327 327 @RequestMapping(value = "/deviceProfileInfos", params = {"pageSize", "page"}, method = RequestMethod.GET)
... ...
... ... @@ -497,7 +497,7 @@ public class EntityQueryController extends BaseController {
497 497 "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
498 498 ENTITY_FILTERS +
499 499 KEY_FILTERS +
500   - TENANT_AND_USER_AUTHORITY_PARAGRAPH;;
  500 + TENANT_OR_USER_AUTHORITY_PARAGRAPH;;
501 501
502 502 private static final String ENTITY_DATA_QUERY_DESCRIPTION =
503 503 "Allows to run complex queries over platform entities (devices, assets, customers, etc) " +
... ... @@ -580,7 +580,7 @@ public class EntityQueryController extends BaseController {
580 580 "\n\n Example mentioned above search all devices which have attribute 'active' set to 'true'. Now let's review available entity filters and key filters syntax:" +
581 581 ENTITY_FILTERS +
582 582 KEY_FILTERS +
583   - TENANT_AND_USER_AUTHORITY_PARAGRAPH;
  583 + TENANT_OR_USER_AUTHORITY_PARAGRAPH;
584 584
585 585
586 586 private static final String ALARM_DATA_QUERY_DESCRIPTION = "This method description defines how Alarm Data Query extends the Entity Data Query. " +
... ...
... ... @@ -91,9 +91,9 @@ public class RpcV2Controller extends AbstractRpcController {
91 91 "In case of persistent RPC, the result of this call is 'rpcId' UUID. In case of lightweight RPC, " +
92 92 "the result of this call is the response from device, or 504 Gateway Timeout if device is offline.";
93 93
94   - private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT + TENANT_AND_USER_AUTHORITY_PARAGRAPH;
  94 + private static final String ONE_WAY_RPC_REQUEST_DESCRIPTION = "Sends the one-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + ONE_WAY_RPC_RESULT + TENANT_OR_USER_AUTHORITY_PARAGRAPH;
95 95
96   - private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT + TENANT_AND_USER_AUTHORITY_PARAGRAPH;
  96 + private static final String TWO_WAY_RPC_REQUEST_DESCRIPTION = "Sends the two-way remote-procedure call (RPC) request to device. " + RPC_REQUEST_DESCRIPTION + TWO_WAY_RPC_RESULT + TENANT_OR_USER_AUTHORITY_PARAGRAPH;
97 97
98 98 @ApiOperation(value = "Send one-way RPC request", notes = ONE_WAY_RPC_REQUEST_DESCRIPTION)
99 99 @ApiResponses(value = {
... ... @@ -131,7 +131,7 @@ public class RpcV2Controller extends AbstractRpcController {
131 131 return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT);
132 132 }
133 133
134   - @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call." + TENANT_AND_USER_AUTHORITY_PARAGRAPH)
  134 + @ApiOperation(value = "Get persistent RPC request", notes = "Get information about the status of the RPC call." + TENANT_OR_USER_AUTHORITY_PARAGRAPH)
135 135 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
136 136 @RequestMapping(value = "/persistent/{rpcId}", method = RequestMethod.GET)
137 137 @ResponseBody
... ... @@ -147,7 +147,7 @@ public class RpcV2Controller extends AbstractRpcController {
147 147 }
148 148 }
149 149
150   - @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_AND_USER_AUTHORITY_PARAGRAPH)
  150 + @ApiOperation(value = "Get persistent RPC requests", notes = "Allows to query RPC calls for specific device using pagination." + TENANT_OR_USER_AUTHORITY_PARAGRAPH)
151 151 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
152 152 @RequestMapping(value = "/persistent/device/{deviceId}", method = RequestMethod.GET)
153 153 @ResponseBody
... ...
... ... @@ -57,7 +57,7 @@ public class TenantController extends BaseController {
57 57 private TenantService tenantService;
58 58
59 59 @ApiOperation(value = "Get Tenant (getTenantById)",
60   - notes = "Fetch the Tenant object based on the provided Tenant Id. " + SYSTEM_AND_TENANT_AUTHORITY_PARAGRAPH)
  60 + notes = "Fetch the Tenant object based on the provided Tenant Id. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
61 61 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
62 62 @RequestMapping(value = "/tenant/{tenantId}", method = RequestMethod.GET)
63 63 @ResponseBody
... ... @@ -79,7 +79,7 @@ public class TenantController extends BaseController {
79 79
80 80 @ApiOperation(value = "Get Tenant Info (getTenantInfoById)",
81 81 notes = "Fetch the Tenant Info object based on the provided Tenant Id. " +
82   - TENANT_INFO_DESCRIPTION + SYSTEM_AND_TENANT_AUTHORITY_PARAGRAPH)
  82 + TENANT_INFO_DESCRIPTION + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
83 83 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
84 84 @RequestMapping(value = "/tenant/info/{tenantId}", method = RequestMethod.GET)
85 85 @ResponseBody
... ...
... ... @@ -108,11 +108,6 @@ public class TenantProfileController extends BaseController {
108 108 "Let's review the example of tenant profile data below: " +
109 109 "\n\n" + MARKDOWN_CODE_BLOCK_START +
110 110 "{\n" +
111   - " \"id\": {\n" +
112   - " \"entityType\": \"TENANT_PROFILE\",\n" +
113   - " \"id\": \"0f2978a0-0d46-11eb-ab90-09ceaa526dd8\"\n" +
114   - " },\n" +
115   - " \"createdTime\": 1602588011818,\n" +
116 111 " \"name\": \"Default\",\n" +
117 112 " \"description\": \"Default tenant profile\",\n" +
118 113 " \"isolatedTbCore\": false,\n" +
... ...
... ... @@ -15,9 +15,9 @@
15 15 */
16 16 package org.thingsboard.server.controller;
17 17
18   -import com.fasterxml.jackson.databind.JsonNode;
19   -import com.fasterxml.jackson.databind.ObjectMapper;
20 18 import com.fasterxml.jackson.databind.node.ObjectNode;
  19 +import io.swagger.annotations.ApiOperation;
  20 +import io.swagger.annotations.ApiParam;
21 21 import lombok.Getter;
22 22 import lombok.RequiredArgsConstructor;
23 23 import org.springframework.beans.factory.annotation.Value;
... ... @@ -32,7 +32,6 @@ import org.springframework.web.bind.annotation.RequestParam;
32 32 import org.springframework.web.bind.annotation.ResponseBody;
33 33 import org.springframework.web.bind.annotation.ResponseStatus;
34 34 import org.springframework.web.bind.annotation.RestController;
35   -import org.thingsboard.common.util.JacksonUtil;
36 35 import org.thingsboard.rule.engine.api.MailService;
37 36 import org.thingsboard.server.common.data.EntityType;
38 37 import org.thingsboard.server.common.data.User;
... ... @@ -52,6 +51,7 @@ import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEven
52 51 import org.thingsboard.server.common.data.security.model.JwtToken;
53 52 import org.thingsboard.server.queue.util.TbCoreComponent;
54 53 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
  54 +import org.thingsboard.server.service.security.model.JwtTokenPair;
55 55 import org.thingsboard.server.service.security.model.SecurityUser;
56 56 import org.thingsboard.server.service.security.model.UserPrincipal;
57 57 import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
... ... @@ -82,20 +82,27 @@ public class UserController extends BaseController {
82 82 private final SystemSecurityService systemSecurityService;
83 83 private final ApplicationEventPublisher eventPublisher;
84 84
  85 + @ApiOperation(value = "Get User (getUserById)",
  86 + notes = "Fetch the User object based on the provided User Id. " +
  87 + "If the user has the authority of 'SYS_ADMIN', the server does not perform additional checks. " +
  88 + "If the user has the authority of 'TENANT_ADMIN', the server checks that the requested user is owned by the same tenant. " +
  89 + "If the user has the authority of 'CUSTOMER_USER', the server checks that the requested user is owned by the same customer.")
85 90 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
86 91 @RequestMapping(value = "/user/{userId}", method = RequestMethod.GET)
87 92 @ResponseBody
88   - public User getUserById(@PathVariable(USER_ID) String strUserId) throws ThingsboardException {
  93 + public User getUserById(
  94 + @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
  95 + @PathVariable(USER_ID) String strUserId) throws ThingsboardException {
89 96 checkParameter(USER_ID, strUserId);
90 97 try {
91 98 UserId userId = new UserId(toUUID(strUserId));
92 99 User user = checkUserId(userId, Operation.READ);
93   - if(user.getAdditionalInfo().isObject()) {
  100 + if (user.getAdditionalInfo().isObject()) {
94 101 ObjectNode additionalInfo = (ObjectNode) user.getAdditionalInfo();
95 102 processDashboardIdFromAdditionalInfo(additionalInfo, DEFAULT_DASHBOARD);
96 103 processDashboardIdFromAdditionalInfo(additionalInfo, HOME_DASHBOARD);
97 104 UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
98   - if(userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) {
  105 + if (userCredentials.isEnabled() && !additionalInfo.has("userCredentialsEnabled")) {
99 106 additionalInfo.put("userCredentialsEnabled", true);
100 107 }
101 108 }
... ... @@ -105,6 +112,10 @@ public class UserController extends BaseController {
105 112 }
106 113 }
107 114
  115 + @ApiOperation(value = "Check Token Access Enabled (isUserTokenAccessEnabled)",
  116 + notes = "Checks that the system is configured to allow administrators to impersonate themself as other users. " +
  117 + "If the user who performs the request has the authority of 'SYS_ADMIN', it is possible to login as any tenant administrator. " +
  118 + "If the user who performs the request has the authority of 'TENANT_ADMIN', it is possible to login as any customer user. ")
108 119 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
109 120 @RequestMapping(value = "/user/tokenAccessEnabled", method = RequestMethod.GET)
110 121 @ResponseBody
... ... @@ -112,10 +123,16 @@ public class UserController extends BaseController {
112 123 return userTokenAccessEnabled;
113 124 }
114 125
  126 + @ApiOperation(value = "Get User Token (getUserToken)",
  127 + notes = "Returns the token of the User based on the provided User Id. " +
  128 + "If the user who performs the request has the authority of 'SYS_ADMIN', it is possible to get the token of any tenant administrator. " +
  129 + "If the user who performs the request has the authority of 'TENANT_ADMIN', it is possible to get the token of any customer user that belongs to the same tenant. ")
115 130 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
116 131 @RequestMapping(value = "/user/{userId}/token", method = RequestMethod.GET)
117 132 @ResponseBody
118   - public JsonNode getUserToken(@PathVariable(USER_ID) String strUserId) throws ThingsboardException {
  133 + public JwtTokenPair getUserToken(
  134 + @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
  135 + @PathVariable(USER_ID) String strUserId) throws ThingsboardException {
119 136 checkParameter(USER_ID, strUserId);
120 137 try {
121 138 if (!userTokenAccessEnabled) {
... ... @@ -130,22 +147,26 @@ public class UserController extends BaseController {
130 147 SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal);
131 148 JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
132 149 JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
133   - ObjectMapper objectMapper = new ObjectMapper();
134   - ObjectNode tokenObject = objectMapper.createObjectNode();
135   - tokenObject.put("token", accessToken.getToken());
136   - tokenObject.put("refreshToken", refreshToken.getToken());
137   - return tokenObject;
  150 + return new JwtTokenPair(accessToken.getToken(), refreshToken.getToken());
138 151 } catch (Exception e) {
139 152 throw handleException(e);
140 153 }
141 154 }
142 155
  156 + @ApiOperation(value = "Save Or update User (saveUser)",
  157 + notes = "Create or update the User. When creating user, platform generates User Id as [time-based UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_(date-time_and_MAC_address). " +
  158 + "The newly created User Id will be present in the response. " +
  159 + "Specify existing User Id to update the device. " +
  160 + "Referencing non-existing User Id will cause 'Not Found' error." +
  161 + "\n\nDevice email is unique for entire platform setup.")
143 162 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
144 163 @RequestMapping(value = "/user", method = RequestMethod.POST)
145 164 @ResponseBody
146   - public User saveUser(@RequestBody User user,
147   - @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail,
148   - HttpServletRequest request) throws ThingsboardException {
  165 + public User saveUser(
  166 + @ApiParam(value = "A JSON value representing the User.", required = true)
  167 + @RequestBody User user,
  168 + @ApiParam(value = "Send activation email (or use activation link)", defaultValue = "true")
  169 + @RequestParam(required = false, defaultValue = "true") boolean sendActivationMail, HttpServletRequest request) throws ThingsboardException {
149 170 try {
150 171
151 172 if (Authority.TENANT_ADMIN.equals(getCurrentUser().getAuthority())) {
... ... @@ -188,10 +209,13 @@ public class UserController extends BaseController {
188 209 }
189 210 }
190 211
  212 + @ApiOperation(value = "Send or re-send the activation email",
  213 + notes = "Force send the activation email to the user. Useful to resend the email if user has accidentally deleted it. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
191 214 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
192 215 @RequestMapping(value = "/user/sendActivationMail", method = RequestMethod.POST)
193 216 @ResponseStatus(value = HttpStatus.OK)
194 217 public void sendActivationEmail(
  218 + @ApiParam(value = "Email of the user", required = true)
195 219 @RequestParam(value = "email") String email,
196 220 HttpServletRequest request) throws ThingsboardException {
197 221 try {
... ... @@ -214,10 +238,14 @@ public class UserController extends BaseController {
214 238 }
215 239 }
216 240
  241 + @ApiOperation(value = "Get the activation link (getActivationLink)",
  242 + notes = "Get the activation link for the user. " +
  243 + "The base url for activation link is configurable in the general settings of system administrator. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
217 244 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
218 245 @RequestMapping(value = "/user/{userId}/activationLink", method = RequestMethod.GET, produces = "text/plain")
219 246 @ResponseBody
220 247 public String getActivationLink(
  248 + @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
221 249 @PathVariable(USER_ID) String strUserId,
222 250 HttpServletRequest request) throws ThingsboardException {
223 251 checkParameter(USER_ID, strUserId);
... ... @@ -239,10 +267,15 @@ public class UserController extends BaseController {
239 267 }
240 268 }
241 269
  270 + @ApiOperation(value = "Delete User (deleteUser)",
  271 + notes = "Deletes the User, it's credentials and all the relations (from and to the User). " +
  272 + "Referencing non-existing User Id will cause an error. " + SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
242 273 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
243 274 @RequestMapping(value = "/user/{userId}", method = RequestMethod.DELETE)
244 275 @ResponseStatus(value = HttpStatus.OK)
245   - public void deleteUser(@PathVariable(USER_ID) String strUserId) throws ThingsboardException {
  276 + public void deleteUser(
  277 + @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
  278 + @PathVariable(USER_ID) String strUserId) throws ThingsboardException {
246 279 checkParameter(USER_ID, strUserId);
247 280 try {
248 281 UserId userId = new UserId(toUUID(strUserId));
... ... @@ -267,14 +300,22 @@ public class UserController extends BaseController {
267 300 }
268 301 }
269 302
  303 + @ApiOperation(value = "Get Users (getUsers)",
  304 + notes = "Returns a page of users owned by tenant or customer. The scope depends on authority of the user that performs the request." +
  305 + PAGE_DATA_PARAMETERS + TENANT_OR_USER_AUTHORITY_PARAGRAPH)
270 306 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
271 307 @RequestMapping(value = "/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
272 308 @ResponseBody
273 309 public PageData<User> getUsers(
  310 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
274 311 @RequestParam int pageSize,
  312 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
275 313 @RequestParam int page,
  314 + @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION)
276 315 @RequestParam(required = false) String textSearch,
  316 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES)
277 317 @RequestParam(required = false) String sortProperty,
  318 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
278 319 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
279 320 try {
280 321 PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder);
... ... @@ -289,15 +330,23 @@ public class UserController extends BaseController {
289 330 }
290 331 }
291 332
  333 + @ApiOperation(value = "Get Tenant Users (getTenantAdmins)",
  334 + notes = "Returns a page of users owned by tenant. " + PAGE_DATA_PARAMETERS + SYSTEM_AUTHORITY_PARAGRAPH)
292 335 @PreAuthorize("hasAuthority('SYS_ADMIN')")
293 336 @RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
294 337 @ResponseBody
295 338 public PageData<User> getTenantAdmins(
296   - @PathVariable("tenantId") String strTenantId,
  339 + @ApiParam(value = TENANT_ID_PARAM_DESCRIPTION, required = true)
  340 + @PathVariable(TENANT_ID) String strTenantId,
  341 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
297 342 @RequestParam int pageSize,
  343 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
298 344 @RequestParam int page,
  345 + @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION)
299 346 @RequestParam(required = false) String textSearch,
  347 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES)
300 348 @RequestParam(required = false) String sortProperty,
  349 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
301 350 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
302 351 checkParameter("tenantId", strTenantId);
303 352 try {
... ... @@ -309,15 +358,23 @@ public class UserController extends BaseController {
309 358 }
310 359 }
311 360
  361 + @ApiOperation(value = "Get Customer Users (getCustomerUsers)",
  362 + notes = "Returns a page of users owned by customer. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
312 363 @PreAuthorize("hasAuthority('TENANT_ADMIN')")
313 364 @RequestMapping(value = "/customer/{customerId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET)
314 365 @ResponseBody
315 366 public PageData<User> getCustomerUsers(
316   - @PathVariable("customerId") String strCustomerId,
  367 + @ApiParam(value = CUSTOMER_ID_PARAM_DESCRIPTION, required = true)
  368 + @PathVariable(CUSTOMER_ID) String strCustomerId,
  369 + @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
317 370 @RequestParam int pageSize,
  371 + @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
318 372 @RequestParam int page,
  373 + @ApiParam(value = USER_TEXT_SEARCH_DESCRIPTION)
319 374 @RequestParam(required = false) String textSearch,
  375 + @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = USER_SORT_PROPERTY_ALLOWABLE_VALUES)
320 376 @RequestParam(required = false) String sortProperty,
  377 + @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES)
321 378 @RequestParam(required = false) String sortOrder) throws ThingsboardException {
322 379 checkParameter("customerId", strCustomerId);
323 380 try {
... ... @@ -331,11 +388,16 @@ public class UserController extends BaseController {
331 388 }
332 389 }
333 390
  391 + @ApiOperation(value = "Enable/Disable User credentials (setUserCredentialsEnabled)",
  392 + notes = "Enables or Disables user credentials. Useful when you would like to block user account without deleting it. " + PAGE_DATA_PARAMETERS + TENANT_AUTHORITY_PARAGRAPH)
334 393 @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN')")
335 394 @RequestMapping(value = "/user/{userId}/userCredentialsEnabled", method = RequestMethod.POST)
336 395 @ResponseBody
337   - public void setUserCredentialsEnabled(@PathVariable(USER_ID) String strUserId,
338   - @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException {
  396 + public void setUserCredentialsEnabled(
  397 + @ApiParam(value = USER_ID_PARAM_DESCRIPTION)
  398 + @PathVariable(USER_ID) String strUserId,
  399 + @ApiParam(value = "Disable (\"true\") or enable (\"false\") the credentials.", defaultValue = "true")
  400 + @RequestParam(required = false, defaultValue = "true") boolean userCredentialsEnabled) throws ThingsboardException {
339 401 checkParameter(USER_ID, strUserId);
340 402 try {
341 403 UserId userId = new UserId(toUUID(strUserId));
... ...