package cc.blynk.server.admin.http.logic; import cc.blynk.core.http.CookiesBaseHttpHandler; import cc.blynk.core.http.MediaType; import cc.blynk.core.http.Response; import cc.blynk.core.http.annotation.*; import cc.blynk.core.http.model.Filter; import cc.blynk.server.Holder; import cc.blynk.server.core.dao.*; import cc.blynk.server.core.model.AppName; import cc.blynk.server.core.model.DashBoard; import cc.blynk.server.core.model.auth.Session; import cc.blynk.server.core.model.auth.User; import cc.blynk.server.core.model.device.Device; import cc.blynk.server.db.DBManager; import cc.blynk.utils.JsonParser; import cc.blynk.utils.SHA256Util; import io.netty.channel.ChannelHandler; import java.util.List; import static cc.blynk.core.http.Response.*; import static cc.blynk.utils.AdminHttpUtil.sort; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 03.12.15. */ @Path("/users") @ChannelHandler.Sharable public class UsersLogic extends CookiesBaseHttpHandler { private final UserDao userDao; private final FileManager fileManager; private final DBManager dbManager; public UsersLogic(Holder holder, String rootPath) { super(holder, rootPath); this.userDao = holder.userDao; this.fileManager = holder.fileManager; this.dbManager = holder.dbManager; } //for tests only public UsersLogic(UserDao userDao, SessionDao sessionDao, DBManager dbManager, FileManager fileManager, TokenManager tokenManager, String rootPath) { super(tokenManager, sessionDao, null, rootPath); this.userDao = userDao; this.fileManager = fileManager; this.dbManager = dbManager; } @GET @Path("") public Response getUsers(@QueryParam("_filters") String filterParam, @QueryParam("_page") int page, @QueryParam("_perPage") int size, @QueryParam("_sortField") String sortField, @QueryParam("_sortDir") String sortOrder) { if (filterParam != null) { Filter filter = JsonParser.readAny(filterParam, Filter.class); filterParam = filter == null ? null : filter.name; } List<User> users = userDao.searchByUsername(filterParam, AppName.ALL); return appendTotalCountHeader( ok(sort(users, sortField, sortOrder), page, size), users.size() ); } @GET @Path("/{id}") public Response getUserByName(@PathParam("id") String id) { String[] parts = slitByLast(id); String email = parts[0]; String appName = parts[1]; User user = userDao.getByName(email, appName); if (user == null) { return notFound(); } return ok(user); } @GET @Path("/names/getAll") public Response getAllUserNames() { return ok(userDao.users.keySet()); } @GET @Path("/token/assign") public Response assignToken(@QueryParam("old") String oldToken, @QueryParam("new") String newToken) { TokenValue tokenValue = tokenManager.getUserByToken(oldToken); if (tokenValue == null) { return badRequest("This token not exists."); } tokenManager.assignToken(tokenValue.user, tokenValue.dashId, tokenValue.deviceId, newToken); return ok(); } @GET @Path("/token/force") public Response forceToken(@QueryParam("email") String email, @QueryParam("app") String app, @QueryParam("dashId") int dashId, @QueryParam("deviceId") int deviceId, @QueryParam("new") String newToken) { User user = userDao.getUsers().get(new UserKey(email, app)); if (user == null) { return badRequest("No user with such email."); } tokenManager.assignToken(user, dashId, deviceId, newToken); return ok(); } @PUT @Consumes(value = MediaType.APPLICATION_JSON) @Path("/{id}") public Response updateUser(@PathParam("id") String id, User updatedUser) { log.debug("Updating user {}", id); String[] parts = slitByLast(id); String name = parts[0]; String appName = parts[1]; User oldUser = userDao.getByName(name, appName); //name was changed, but not password - do not allow this. //as name is used as salt for pass generation if (!updatedUser.email.equals(oldUser.email) && updatedUser.pass.equals(oldUser.pass)) { return badRequest("You need also change password when changing email."); } //user name was changed if (!updatedUser.email.equals(oldUser.email)) { deleteUserByName(id); for (DashBoard dashBoard : oldUser.profile.dashBoards) { for (Device device : dashBoard.devices) { tokenManager.assignToken(updatedUser, dashBoard.id, device.id, device.token); } } } //if pass was changed, call hash function. if (!updatedUser.pass.equals(oldUser.pass)) { log.debug("Updating pass for {}.", updatedUser.email); updatedUser.pass = SHA256Util.makeHash(updatedUser.pass, updatedUser.email); } userDao.add(updatedUser); updatedUser.lastModifiedTs = System.currentTimeMillis(); log.debug("Adding new user {}", updatedUser.email); return ok(updatedUser); } @DELETE @Path("/{id}") public Response deleteUserByName(@PathParam("id") String id) { String[] parts = slitByLast(id); String email = parts[0]; String appName = parts[1]; UserKey userKey = new UserKey(email, appName); User user = userDao.delete(userKey); if (user == null) { return notFound(); } if (!fileManager.delete(email, appName)) { return notFound(); } dbManager.deleteUser(userKey); Session session = sessionDao.userSession.remove(userKey); if (session != null) { session.closeAll(); } log.info("User {} successfully removed.", email); return ok(); } private String[] slitByLast(String id) { int i = id.lastIndexOf("-"); return new String[] { id.substring(0, i), id.substring(i + 1) }; } }