BloggerService.java
package sk.iway.iwcm.components.blog.rest;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;
import javax.servlet.http.HttpServletRequest;
import org.json.JSONObject;
import sk.iway.Password;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.Identity;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.common.CloudToolsForCore;
import sk.iway.iwcm.common.UploadFileTools;
import sk.iway.iwcm.common.UserTools;
import sk.iway.iwcm.components.blog.jpa.BloggerBean;
import sk.iway.iwcm.components.users.AuthorizeUserService;
import sk.iway.iwcm.components.users.userdetail.UserDetailsEntity;
import sk.iway.iwcm.components.users.userdetail.UserDetailsRepository;
import sk.iway.iwcm.components.users.userdetail.UserDetailsService;
import sk.iway.iwcm.database.ComplexQuery;
import sk.iway.iwcm.database.Mapper;
import sk.iway.iwcm.database.SimpleQuery;
import sk.iway.iwcm.doc.DocDB;
import sk.iway.iwcm.doc.DocDetails;
import sk.iway.iwcm.doc.GroupDetails;
import sk.iway.iwcm.doc.GroupsDB;
import sk.iway.iwcm.editor.facade.EditorFacade;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.io.IwcmFile;
import sk.iway.iwcm.system.ModuleInfo;
import sk.iway.iwcm.system.Modules;
import sk.iway.iwcm.users.UsersDB;
public class BloggerService {
private BloggerService() {}
private static final String QUERY_PREFIX_ALL = "SELECT user_id, first_name, last_name, login, email, editable_groups FROM users WHERE";
private static final String QUERY_PREFIX_ID = "SELECT user_id FROM users WHERE";
/********************************* GET *********************************************/
/**
* Get BloggerBean by bloggerId
* @param bloggerId
* @return
*/
public static BloggerBean getBloggerBean(long bloggerId) {
StringBuilder query = new StringBuilder(QUERY_PREFIX_ALL);
query.append(" user_id = ").append(bloggerId);
query.append(CloudToolsForCore.getDomainIdSqlWhere(true));
GroupsDB groupsDB = GroupsDB.getInstance();
List<BloggerBean> blogger = new ArrayList<>();
new ComplexQuery().setSql(query.toString()).list(new Mapper<BloggerBean>() {
@Override
public BloggerBean map(ResultSet rs) throws SQLException {
blogger.add( resultSetToBean(rs, groupsDB) );
return null;
}
});
return blogger.isEmpty() ? null : blogger.get(0);
}
/**
* Get all bloggers (aka user that belongs to BLOG group)
* @return
*/
public static List<BloggerBean> getAllBloggers() {
StringBuilder query = new StringBuilder(QUERY_PREFIX_ALL);
addQueryConditions(query);
GroupsDB groupsDB = GroupsDB.getInstance();
List<BloggerBean> bloggers = new ArrayList<>();
new ComplexQuery().setSql(query.toString()).list(new Mapper<BloggerBean>() {
@Override
public BloggerBean map(ResultSet rs) throws SQLException {
bloggers.add( resultSetToBean(rs, groupsDB) );
return null;
}
});
return bloggers;
}
/**
* Convert result set to BloggerBean, and return bean
* @param rs
* @param groupsDB
* @return
* @throws SQLException
*/
private static BloggerBean resultSetToBean(ResultSet rs, GroupsDB groupsDB) throws SQLException{
BloggerBean blogger = new BloggerBean();
blogger.setId(rs.getLong("user_id"));
blogger.setFirstName(rs.getString("first_name"));
blogger.setLastName(rs.getString("last_name"));
blogger.setLogin(rs.getString("login"));
blogger.setEmail(rs.getString("email"));
//Set password as unchanged
blogger.setPassword(UserTools.PASS_UNCHANGED);
String editableGroups = rs.getString("editable_groups");
int[] editableGroupsIds = Tools.getTokensInt(editableGroups, ",");
if(editableGroupsIds.length > 0) blogger.setEditableGroup( groupsDB.getGroup(editableGroupsIds[0]) );
return blogger;
}
/********************************* EDIT *********************************************/
/**
* Edit blogger -> aka get UserDetailsEntity by bloggerId, and edit/save it
* @param bloggerToEdit
* @param userDetailsRepository
* @return
*/
public static boolean editBlogger(BloggerBean bloggerToEdit, UserDetailsRepository userDetailsRepository, HttpServletRequest request) {
UserDetailsEntity userBlogger = userDetailsRepository.getById(bloggerToEdit.getId());
//Field's login AND editableGroups CANT BE CHANGE
//Copy ONLY remain fields
userBlogger.setFirstName( bloggerToEdit.getFirstName() );
userBlogger.setLastName( bloggerToEdit.getLastName() );
userBlogger.setEmail( bloggerToEdit.getEmail() );
//Update user
userDetailsRepository.save(userBlogger);
//After save, set password back
boolean sendWelcomeEmail = false;
String password = bloggerToEdit.getPassword();
if (Tools.isEmpty(password) || "*".equals(password)) {
password = Password.generatePassword(8);
bloggerToEdit.setPassword( password );
sendWelcomeEmail = true;
}
//Now CHANGE password
userBlogger.setPassword( bloggerToEdit.getPassword() );
//Update user password (if needed)
boolean passwordSaved = UserDetailsService.savePassword(bloggerToEdit.getPassword(), userBlogger.getId().intValue());
if (passwordSaved && sendWelcomeEmail) {
//Send welcome email again
AuthorizeUserService.sendInfoEmail(userBlogger, password, UsersDB.getCurrentUser(request), request);
}
return passwordSaved;
}
/********************************* INSERT *********************************************/
/**
* Perform whooole process of saving new blogger.
* Including: creating new user of type blogger (with all needed rights and perms), create bloger structure (root group + 1doc, default sub group + 2doc's) AND send email to user (aka blogger) about adding him to blog group
* @param bloggerToSave
* @param userDetailsRepository
* @param editorFacade
* @param request
* @return
*/
public static boolean saveBlogger(BloggerBean bloggerToSave, UserDetailsRepository userDetailsRepository, EditorFacade editorFacade, HttpServletRequest request) {
UserDetailsEntity newUser = new UserDetailsEntity();
newUser.setId((long)-1);
newUser.setFirstName( bloggerToSave.getFirstName() );
newUser.setLastName( bloggerToSave.getLastName() );
newUser.setEmail( bloggerToSave.getEmail() );
newUser.setRegDate(new Date());
//Set loggin and Writable folders
String login = bloggerToSave.getLogin();
newUser.setLogin( login );
//Blog groupID (without this group id, user not gonna be showed in blogger's list)
newUser.setUserGroupsIds( "" + DocDB.getBlogGroupId() );
//Need to set
newUser.setForumRank(0);
newUser.setRatingRank(0);
newUser.setParentId(0);
newUser.setAdmin(true);
newUser.setAuthorized(true);
//First save password as null for save
newUser.setPassword(null);
//Save new blogger user
userDetailsRepository.save(newUser);
//Get new saved user
Integer newUserId = UsersDB.getUserIdByLogin(login);
if(newUserId == null) return false;
newUser.setId( newUserId.longValue() );
bloggerToSave.setId( newUserId.longValue() );
//After save, set password back
String password = bloggerToSave.getPassword();
if (Tools.isEmpty(password) || "*".equals(password)) password = Password.generatePassword(8);
newUser.setPassword( password );
//Set user rights
setUserRights(newUserId);
//Set user password
boolean savedPassword = UserDetailsService.savePassword(password, newUserId);
if(!savedPassword) return false;
//MAKE - blogger structure
prepareBloggerStructure(newUser, bloggerToSave.getEditableGroup(), userDetailsRepository, editorFacade, request);
//Send welcome email
AuthorizeUserService.sendInfoEmail(newUser, password, UsersDB.getCurrentUser(request), request);
return true;
}
private static void setUserRights(int userId) {
(new SimpleQuery()).execute("DELETE FROM user_disabled_items WHERE user_id=?", userId);
StringBuilder sb = new StringBuilder("INSERT INTO user_disabled_items VALUES");
List<ModuleInfo> modules = Modules.getInstance().getModules();
String[] defaulPerm = {"cmp_blog", "addPage", "pageSave", "deletePage", "addSubdir", "cmp_diskusia" };
String[] bonusPerm = Tools.getTokens( Constants.getString("bloggerAppPermissions") , ",");
Set<String> duplicity = new HashSet<>();
for(ModuleInfo module : modules){
//
if(module == null || module.getItemKey() == null || Arrays.stream(defaulPerm).anyMatch(module.getItemKey()::equals) || Arrays.stream(bonusPerm).anyMatch(module.getItemKey()::equals)) continue;
//If duplicity, skip
if(duplicity.contains(module.getItemKey())==false) {
duplicity.add(module.getItemKey());
sb.append(" (").append(userId).append(",'").append(module.getItemKey()).append("'),");
}
//Submodules
if(module.getSubmenus() == null) continue;
for (ModuleInfo subModule : module.getSubmenus()) {
//
if(subModule == null || subModule.getItemKey() == null || Arrays.stream(defaulPerm).anyMatch(subModule.getItemKey()::equals) || Arrays.stream(bonusPerm).anyMatch(subModule.getItemKey()::equals)) continue;
//If duplicity, skip
if(duplicity.contains(subModule.getItemKey())) continue;
duplicity.add(subModule.getItemKey());
sb.append(" (").append(userId).append(",'").append(subModule.getItemKey()).append("'),");
}
}
//If SB does not contain cmp_blog_admin, add it
if( sb.indexOf("(" + userId + ",'cmp_blog_admin'),") == -1 ) sb.append(" (").append(userId).append(",'cmp_blog_admin'),");
//Remove last ','
sb.deleteCharAt(sb.length() - 1);
(new SimpleQuery()).execute(sb.toString());
}
/**
* Prepare blogger structure of 2 groups and 3 docs.
* @param bloggerUser
* @param parentGroup
* @param userDetailsRepository
* @param editorFacade
* @param request
*/
private static void prepareBloggerStructure(UserDetailsEntity bloggerUser, GroupDetails parentGroup, UserDetailsRepository userDetailsRepository, EditorFacade editorFacade, HttpServletRequest request) {
//Create root group
GroupDetails rootGroup = createGroup(bloggerUser.getLogin(), bloggerUser.getId().intValue(), parentGroup, null);
//Check if root group was made right now
if(rootGroup != null) {
int authorId = ((Identity) request.getSession().getAttribute(Constants.USER_KEY)).getUserId();
Prop prop = Prop.getInstance(request);
StringBuilder writableFolders = new StringBuilder();
writableFolders.append(UploadFileTools.getPageUploadSubDir(-1, rootGroup.getGroupId(), null, "/images")).append("/*\n");
writableFolders.append(UploadFileTools.getPageUploadSubDir(-1, rootGroup.getGroupId(), null, "/files")).append("/*\n");
writableFolders.append(UploadFileTools.getPageUploadSubDir(-1, rootGroup.getGroupId(), null, "/images/gallery")).append("/*\n");
//Set for user new editable group (blogger root group)
userDetailsRepository.updateEditableGroupsWritableFolders(""+rootGroup.getGroupId(), writableFolders.toString(), bloggerUser.getId());
//Create root group NEWS DOC
createGroupNewsDoc(editorFacade, rootGroup.getGroupId(), rootGroup.getGroupName(), authorId, bloggerUser.getId().intValue());
//Create default sub group of root group
GroupDetails defaultSubGroup = createGroup(bloggerUser.getLogin(), bloggerUser.getId().intValue(), rootGroup, prop.getText("components.blog.default_group_name"));
if (defaultSubGroup != null) {
//Create default sub group NEWS DOC
createGroupNewsDoc(editorFacade, defaultSubGroup.getGroupId(), defaultSubGroup.getGroupName(), authorId, bloggerUser.getId().intValue());
// //Create example doc
createExampleDoc(editorFacade, defaultSubGroup.getGroupId(), prop.getText("components.blog.default_page_title"), authorId, bloggerUser.getId().intValue() , prop.getText("components.blog.default_page_text"));
}
//
createDirectoriesBloggerCanAccess( writableFolders.toString() );
}
}
/**
* Create new group
* @param userLogin
* @param userId
* @param parentGroup
* @param groupName
* @return
*/
private static GroupDetails createGroup(String userLogin, int userId, GroupDetails parentGroup, String groupName) {
//Check if group allready exist
GroupDetails newGroup = GroupsDB.getInstance().getGroup(userLogin, parentGroup.getGroupId());
if(newGroup != null) return null;
//Create new root group
newGroup = new GroupDetails();
newGroup.setParentGroupId( parentGroup.getGroupId() );
newGroup.setGroupName( Tools.isEmpty(groupName) ? userLogin : groupName );
newGroup.setTempId( parentGroup.getTempId() );
newGroup.setFieldA( String.valueOf(userId) );
GroupsDB.getInstance().setGroup(newGroup);
return newGroup;
}
private static void createGroupNewsDoc(EditorFacade editorFacade, int rootGroupId, String docTitle, int authorId, int bloggerId) {
DocDetails groupDoc = editorFacade.getDocForEditor(-1, -1, rootGroupId);
//Set doc
groupDoc.setTitle(docTitle);
groupDoc.setNavbar(docTitle);
groupDoc.setData(Prop.getInstance().getText("components.blog.atricles-code", ""+rootGroupId));
groupDoc.setAuthorId(authorId);
groupDoc.setAvailable(true);
groupDoc.setSearchable(true);
groupDoc.setCacheable(false);
//Save doc
editorFacade.save(groupDoc);
updateAuthorId(groupDoc.getDocId(), bloggerId);
}
private static void updateAuthorId(int docId, int authorId) {
(new SimpleQuery()).execute("UPDATE documents SET author_id=? WHERE doc_id=?", authorId, docId);
}
private static void createExampleDoc(EditorFacade editorFacade, int rootGroupId, String docTitle, int authorId, int bloggerId, String docData) {
DocDetails groupDoc = editorFacade.getDocForEditor(-1, -1, rootGroupId);
//Set doc
groupDoc.setTitle(docTitle);
groupDoc.setNavbar(docTitle);
groupDoc.setData(docData);
groupDoc.setAuthorId(authorId);
groupDoc.setAvailable(true);
groupDoc.setSearchable(true);
groupDoc.setCacheable(false);
//Save doc
editorFacade.save(groupDoc);
updateAuthorId(groupDoc.getDocId(), bloggerId);
}
private static void createDirectoriesBloggerCanAccess(String writableFolders) {
String[] folders = Tools.getTokens(writableFolders, "\n");
for(String folder : folders) {
folder = folder.substring(0, folder.lastIndexOf("/")+1);
IwcmFile file = new IwcmFile(Tools.getRealPath(folder));
file.mkdirs();
}
}
/********************************* SUPPORT METHODS *********************************************/
/**
* Return groupID's of all users of type bloggers
* @return
*/
public static List<Integer> getAllBloggersGroupIds() {
List<Integer> allGroupIds = new ArrayList<>();
for(Integer rootGroupId : getAllBloggersRootGroupIds())
addBloggerGroupIds(rootGroupId, allGroupIds);
return allGroupIds;
}
/**
* Get groupTree based on rootGroupId and push groupIds into bloggerGroupIds list
* @param bloggerRootGroupId
* @param bloggerGroupIds
*/
private static void addBloggerGroupIds(int bloggerRootGroupId, List<Integer> bloggerGroupIds) {
//Get groups tree from user editable root group
List<GroupDetails> groopsTree = GroupsDB.getInstance().getGroupsTree(bloggerRootGroupId, true, true);
for(GroupDetails group : groopsTree) {
bloggerGroupIds.add(group.getGroupId());
}
}
/**
* Get all rootGroupIds (aka editabelGroup) of all users of type bloggers
* @return
*/
public static List<Integer> getAllBloggersRootGroupIds() {
List<Integer> bloggerIds = getAllBloggersIds();
if (bloggerIds.isEmpty()) return new ArrayList<>(0);
StringBuilder bloggerIdsSb = new StringBuilder("(");
for(Integer bloggerId : bloggerIds) bloggerIdsSb.append(bloggerId).append(",");
//Remove last ','
bloggerIdsSb.deleteCharAt(bloggerIdsSb.length() - 1);
//Add enclosing ')'
bloggerIdsSb.append(")");
//
List<String> rootGroupIdsString = (new SimpleQuery()).forListString("SELECT editable_groups FROM users WHERE user_id IN " + bloggerIdsSb.toString() + CloudToolsForCore.getDomainIdSqlWhere(true));
//
List<Integer> rootGroupIds = new ArrayList<>();
for(String rootGroupId : rootGroupIdsString) {
if(Tools.isEmpty(rootGroupId)) continue;
rootGroupIds.add( Tools.getTokensInt(rootGroupId, ",")[0] );
}
return rootGroupIds;
}
/**
* Get id of all users of type bloggers
* @return
*/
private static List<Integer> getAllBloggersIds() {
StringBuilder query = new StringBuilder(QUERY_PREFIX_ID);
addQueryConditions(query);
return (new SimpleQuery()).forListInteger(query.toString());
}
/**
* A LIKE condtion to find by user_group (all combinations)
* @param query
*/
private static void addQueryConditions(StringBuilder query) {
int blogGroupId = DocDB.getBlogGroupId();
query.append("(user_groups LIKE '").append(blogGroupId).append("' OR ");
query.append("user_groups LIKE '%,").append(blogGroupId).append("' OR ");
query.append("user_groups LIKE '").append(blogGroupId).append(",%' OR ");
query.append("user_groups LIKE '%,").append(blogGroupId).append(",%') ");
query.append(CloudToolsForCore.getDomainIdSqlWhere(true));
}
/**
* User is considerred blogger if he have perm cmp_blog AND he is inside of blog userGroup
* @param user
* @return
*/
public static boolean isUserBlogger(Identity user) {
//FIRST check if user have cmp_blog permission
if(!user.isEnabledItem("cmp_blog")) return false;
//SECOND check if user is inside of blog userGroup
int blogGroupId = DocDB.getBlogGroupId();
int[] userGroupIds = Tools.getTokensInt(user.getUserGroupsIds(), ",");
return IntStream.of( userGroupIds ).anyMatch(x -> x == blogGroupId);
}
/**
* User is considered blogger admin if he have perm cmp_blog_admin AND he is admin
* @param user
* @return
*/
public static boolean isUserBloggerAdmin(Identity user) {
return (user.isAdmin() && user.isEnabledItem("cmp_blog_admin"));
}
/**
* Verify if user is blogger or blogger admin
* @param user
* @return
*/
public static boolean isUserBloggerOrBloggerAdmin(Identity user) {
return isUserBlogger(user) || isUserBloggerAdmin(user);
}
/**
* Add new GROUP to blogger structure
* @param currentUser
* @param customData
* @return
*/
public static boolean addNewBloggerGroup(EditorFacade editorFacade, Identity currentUser, String customData) {
boolean isBloggerAdmin = BloggerService.isUserBloggerAdmin( currentUser );
boolean isBlogger = BloggerService.isUserBlogger( currentUser );
//Check perms
if(isBloggerAdmin==false && isBlogger==false) return false;
int groupId = -1;
String newGroupName = "";
if(customData != null && !customData.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(customData);
groupId = Tools.getIntValue((String) jsonObject.get("groupId"), -1);
newGroupName = (String) jsonObject.get("newGroupName");
} catch (Exception ex) {
sk.iway.iwcm.Logger.error(ex);
return false;
}
}
if(Tools.isEmpty(newGroupName)) return false;
if(groupId < 1) {
if(isBlogger) groupId = Tools.getTokensInt(currentUser.getEditableGroups(), ",")[0];
else return false; //It's admin not casual blogger
} else {
//Check perms
//If user is blogger admin, check if group is blogger group
if(isBloggerAdmin) {
List<Integer> allBloggersGroupIds = BloggerService.getAllBloggersRootGroupIds();
if(Boolean.FALSE.equals( allBloggersGroupIds.contains(groupId) )) return false;
} //If user is blogger, check if he has perm to selected group
else if(GroupsDB.isGroupEditable(currentUser, groupId)==false) {
return false;
}
}
//All is ok, create group
GroupDetails newGroup = createGroup(currentUser.getLogin(), currentUser.getUserId(), GroupsDB.getInstance().getGroup(groupId), newGroupName);
if (newGroup != null) {
createGroupNewsDoc(editorFacade, newGroup.getGroupId(), newGroup.getGroupName(), currentUser.getUserId(), currentUser.getUserId());
return true;
}
return false;
}
}