com.erudika.scoold.utils.ScooldUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.erudika.scoold.utils.ScooldUtils.java

Source

/*
 * Copyright 2013-2019 Erudika. https://erudika.com
 *
 * 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.
 *
 * For issues and patches go to: https://github.com/erudika
 */
package com.erudika.scoold.utils;

import com.erudika.para.client.ParaClient;
import com.erudika.para.core.ParaObject;
import com.erudika.para.core.Sysprop;
import com.erudika.para.core.User;
import com.erudika.para.core.utils.ParaObjectUtils;
import com.erudika.para.email.Emailer;
import com.erudika.para.utils.Config;
import com.erudika.para.utils.Pager;
import com.erudika.para.utils.Utils;
import com.erudika.para.validation.ValidationUtils;
import static com.erudika.scoold.ScooldServer.*;
import com.erudika.scoold.core.Comment;
import com.erudika.scoold.core.Post;
import com.erudika.scoold.core.Profile;
import static com.erudika.scoold.core.Profile.Badge.ENTHUSIAST;
import static com.erudika.scoold.core.Profile.Badge.TEACHER;
import com.erudika.scoold.core.Revision;
import static com.erudika.scoold.utils.HttpUtils.getCookieValue;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.ConstraintViolation;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 *
 * @author Alex Bogdanovski [alex@erudika.com]
 */
@Component
@Named
public final class ScooldUtils {

    private static final Logger logger = LoggerFactory.getLogger(ScooldUtils.class);
    private static final Map<String, String> EMAIL_TEMPLATES = new ConcurrentHashMap<String, String>();
    private static final Set<String> APPROVED_DOMAINS = new HashSet<>();
    private static final Set<String> ADMINS = new HashSet<>();
    private static boolean connectionError = false;

    private ParaClient pc;
    private LanguageUtils langutils;
    private static ScooldUtils instance;
    @Inject
    private Emailer emailer;

    @Inject
    public ScooldUtils(ParaClient pc, LanguageUtils langutils) {
        this.pc = pc;
        this.langutils = langutils;
    }

    public ParaClient getParaClient() {
        return pc;
    }

    public LanguageUtils getLangutils() {
        return langutils;
    }

    public static ScooldUtils getInstance() {
        return instance;
    }

    static void setInstance(ScooldUtils instance) {
        ScooldUtils.instance = instance;
    }

    static {
        // multiple domains/admins are now allowed only in Scoold PRO
        String approvedDomains = Config.getConfigParam("approved_domains_for_signups", "");
        if (!StringUtils.isBlank(approvedDomains)) {
            APPROVED_DOMAINS.add(approvedDomains);
        }
        // multiple admins are now allowed only in Scoold PRO
        String admins = Config.getConfigParam("admins", "");
        if (!StringUtils.isBlank(admins)) {
            ADMINS.add(admins);
        }
    }

    public Profile checkAuth(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        Profile authUser = null;
        if (HttpUtils.getStateParam(Config.AUTH_COOKIE, req) != null) {
            User u = pc.me(HttpUtils.getStateParam(Config.AUTH_COOKIE, req));
            if (u != null && isEmailDomainApproved(u.getEmail())) {
                authUser = pc.read(Profile.id(u.getId()));
                if (authUser == null) {
                    authUser = new Profile(u.getId(), u.getName());
                    authUser.setPicture(u.getPicture());
                    authUser.setAppid(u.getAppid());
                    authUser.setCreatorid(u.getId());
                    authUser.setTimestamp(u.getTimestamp());
                    authUser.setGroups(isRecognizedAsAdmin(u) ? User.Groups.ADMINS.toString() : u.getGroups());
                    authUser.create();
                    if (!u.getIdentityProvider().equals("generic")) {
                        sendWelcomeEmail(u, false, req);
                    }
                    logger.info("Created new user '{}' with id={}, groups={}.", u.getName(), authUser.getId(),
                            authUser.getGroups());
                }
                boolean update = false;
                if (!isAdmin(authUser) && isRecognizedAsAdmin(u)) {
                    logger.info("User '{}' with id={} promoted to admin.", u.getName(), authUser.getId());
                    authUser.setGroups(User.Groups.ADMINS.toString());
                    update = true;
                } else if (isAdmin(authUser) && !isRecognizedAsAdmin(u)) {
                    logger.info("User '{}' with id={} demoted to regular user.", u.getName(), authUser.getId());
                    authUser.setGroups(User.Groups.USERS.toString());
                    update = true;
                }
                authUser.setUser(u);
                if (!StringUtils.equals(u.getPicture(), authUser.getPicture())
                        && !StringUtils.contains(authUser.getPicture(), "gravatar.com")) {
                    authUser.setPicture(u.getPicture());
                    update = true;
                }
                if (update) {
                    authUser.update();
                }
            } else {
                clearSession(req, res);
                logger.warn("Attempted signin from an unknown domain: {}", u != null ? u.getEmail() : "unknown");
                res.setStatus(401);
            }
        }
        initCSRFToken(req, res);
        return authUser;
    }

    public void sendWelcomeEmail(User user, boolean verifyEmail, HttpServletRequest req) {
        // send welcome email notification
        if (user != null) {
            Map<String, Object> model = new HashMap<String, Object>();
            Map<String, String> lang = getLang(req);
            String subject = Utils.formatMessage(lang.get("signin.welcome"), Config.APP_NAME);
            String body1 = Utils.formatMessage(lang.get("signin.welcome.body1"), Config.APP_NAME) + "<br><br>";
            String body2 = lang.get("signin.welcome.body2") + "<br><br>";
            String body3 = "Best, <br>The Scoold team";

            if (verifyEmail && !user.getActive() && !StringUtils.isBlank(user.getIdentifier())) {
                Sysprop s = pc.read(user.getIdentifier());
                if (s != null) {
                    String token = Utils.base64encURL(Utils.generateSecurityToken().getBytes());
                    s.addProperty(Config._EMAIL_TOKEN, token);
                    pc.update(s);
                    token = getServerURL() + CONTEXT_PATH + SIGNINLINK + "/register?id=" + user.getId() + "&token="
                            + token;
                    body3 = "<b><a href=\"" + token + "\">" + lang.get("signin.welcome.verify")
                            + "</a></b><br><br>";
                    body3 += "Best, <br>The Scoold team<br><br>";
                }
            }

            model.put("logourl", Config.getConfigParam("small_logo_url", "https://scoold.com/logo.png"));
            model.put("heading", Utils.formatMessage(lang.get("signin.welcome.title"), user.getName()));
            model.put("body", body1 + body2 + body3);
            emailer.sendEmail(Arrays.asList(user.getEmail()), subject,
                    Utils.compileMustache(model, loadEmailTemplate("notify")));
        }
    }

    public void sendPasswordResetEmail(String email, String token, HttpServletRequest req) {
        if (email != null && token != null) {
            Map<String, Object> model = new HashMap<String, Object>();
            Map<String, String> lang = getLang(req);
            String url = getServerURL() + CONTEXT_PATH + SIGNINLINK + "/iforgot?email=" + email + "&token=" + token;
            String subject = lang.get("iforgot.title");
            String body1 = "Open the link below to change your password:<br><br>";
            String body2 = Utils.formatMessage("<b><a href=\"{0}\">RESET PASSWORD</a></b><br><br>", url);
            String body3 = "Best, <br>The Scoold team<br><br>";

            model.put("logourl", Config.getConfigParam("small_logo_url", "https://scoold.com/logo.png"));
            model.put("heading", lang.get("hello"));
            model.put("body", body1 + body2 + body3);
            emailer.sendEmail(Arrays.asList(email), subject,
                    Utils.compileMustache(model, loadEmailTemplate("notify")));
        }
    }

    public boolean isEmailDomainApproved(String email) {
        if (StringUtils.isBlank(email)) {
            return false;
        }
        if (!APPROVED_DOMAINS.isEmpty()) {
            return APPROVED_DOMAINS.contains(StringUtils.substringAfter(email, "@"));
        }
        return true;
    }

    public void initCSRFToken(HttpServletRequest req, HttpServletResponse res) {
        String csrfInSession = (String) req.getSession(true).getAttribute(TOKEN_PREFIX + "CSRF");
        //String csrfInCookie = Utils.getStateParam(CSRF_COOKIE, req);
        if (StringUtils.isBlank(csrfInSession)) {
            csrfInSession = Utils.generateSecurityToken();
            req.getSession(true).setAttribute(TOKEN_PREFIX + "CSRF", csrfInSession);
        }
        HttpUtils.setStateParam(CSRF_COOKIE, csrfInSession, req, res);
    }

    public Profile getAuthUser(HttpServletRequest req) {
        return (Profile) req.getAttribute(AUTH_USER_ATTRIBUTE);
    }

    public boolean isAuthenticated(HttpServletRequest req) {
        return getAuthUser(req) != null;
    }

    public boolean isNearMeFeatureEnabled() {
        return Config.getConfigBoolean("nearme_feature_enabled", true);
    }

    public boolean isDefaultSpacePublic() {
        return Config.getConfigBoolean("is_default_space_public", true);
    }

    public static boolean connectionError() {
        return connectionError;
    }

    public static void setConnectionError(boolean value) {
        connectionError = value;
    }

    public Pager getPager(String pageParamName, HttpServletRequest req) {
        return new Pager(NumberUtils.toInt(req.getParameter(pageParamName), 1), Config.MAX_ITEMS_PER_PAGE);
    }

    public String getLanguageCode(HttpServletRequest req) {
        String cookieLoc = getCookieValue(req, LOCALE_COOKIE);
        Locale requestLocale = langutils.getProperLocale(req.getLocale().toString());
        return (cookieLoc != null) ? cookieLoc : requestLocale.getLanguage();
    }

    public Locale getCurrentLocale(String langname, HttpServletRequest req) {
        Locale currentLocale = langutils.getProperLocale(langname);
        if (currentLocale == null) {
            currentLocale = langutils.getProperLocale("en");
        }
        return currentLocale;
    }

    public Map<String, String> getLang(HttpServletRequest req) {
        return getLang(getCurrentLocale(getLanguageCode(req), req));
    }

    public Map<String, String> getLang(Locale currentLocale) {
        Map<String, String> lang = langutils.readLanguage(currentLocale.toString());
        if (lang == null || lang.isEmpty()) {
            lang = langutils.getDefaultLanguage();
        }
        return lang;
    }

    public boolean isLanguageRTL(String langCode) {
        return StringUtils.equalsAnyIgnoreCase(langCode, "ar", "he", "dv", "iw", "fa", "ps", "sd", "ug", "ur",
                "yi");
    }

    public void fetchProfiles(List<? extends ParaObject> objects) {
        if (objects == null || objects.isEmpty()) {
            return;
        }
        Map<String, String> authorids = new HashMap<String, String>(objects.size());
        Map<String, Profile> authors = new HashMap<String, Profile>(objects.size());
        for (ParaObject obj : objects) {
            if (obj.getCreatorid() != null) {
                authorids.put(obj.getId(), obj.getCreatorid());
            }
        }
        List<String> ids = new ArrayList<String>(new HashSet<String>(authorids.values()));
        if (ids.isEmpty()) {
            return;
        }
        // read all post authors in batch
        for (ParaObject author : pc.readAll(ids)) {
            authors.put(author.getId(), (Profile) author);
        }
        // set author object for each post
        for (ParaObject obj : objects) {
            if (obj instanceof Post) {
                ((Post) obj).setAuthor(authors.get(authorids.get(obj.getId())));
            } else if (obj instanceof Revision) {
                ((Revision) obj).setAuthor(authors.get(authorids.get(obj.getId())));
            }
        }
    }

    //get the comments for each answer and the question
    public void getComments(List<Post> allPosts) {
        Map<String, List<Comment>> allComments = new HashMap<String, List<Comment>>();
        List<String> allCommentIds = new ArrayList<String>();
        List<Post> forUpdate = new ArrayList<Post>(allPosts.size());
        // get the comment ids of the first 5 comments for each post
        for (Post post : allPosts) {
            // not set => read comments if any and embed ids in post object
            if (post.getCommentIds() == null) {
                forUpdate.add(reloadFirstPageOfComments(post));
                allComments.put(post.getId(), post.getComments());
            } else {
                // ids are set => add them to list for bulk read
                allCommentIds.addAll(post.getCommentIds());
            }
        }
        if (!allCommentIds.isEmpty()) {
            // read all comments for all posts on page in bulk
            for (ParaObject comment : pc.readAll(allCommentIds)) {
                List<Comment> postComments = allComments.get(comment.getParentid());
                if (postComments == null) {
                    allComments.put(comment.getParentid(), new ArrayList<Comment>());
                }
                allComments.get(comment.getParentid()).add((Comment) comment);
            }
        }
        // embed comments in each post for use within the view
        for (Post post : allPosts) {
            List<Comment> cl = allComments.get(post.getId());
            long clSize = (cl == null) ? 0 : cl.size();
            if (post.getCommentIds().size() != clSize) {
                forUpdate.add(reloadFirstPageOfComments(post));
                clSize = post.getComments().size();
            } else {
                post.setComments(cl);
            }
            post.getItemcount().setCount(clSize + 1L); // hack to show the "more" button
        }
        if (!forUpdate.isEmpty()) {
            pc.updateAll(allPosts);
        }
    }

    public Post reloadFirstPageOfComments(Post post) {
        List<Comment> commentz = pc.getChildren(post, Utils.type(Comment.class), post.getItemcount());
        ArrayList<String> ids = new ArrayList<String>(commentz.size());
        for (Comment comment : commentz) {
            ids.add(comment.getId());
        }
        post.setCommentIds(ids);
        post.setComments(commentz);
        return post;
    }

    public void updateViewCount(Post showPost, HttpServletRequest req, HttpServletResponse res) {
        //do not count views from author
        if (showPost != null && !isMine(showPost, getAuthUser(req))) {
            String postviews = HttpUtils.getStateParam("postviews", req);
            if (!StringUtils.contains(postviews, showPost.getId())) {
                long views = (showPost.getViewcount() == null) ? 0 : showPost.getViewcount();
                showPost.setViewcount(views + 1); //increment count
                HttpUtils.setStateParam("postviews", postviews + "," + showPost.getId(), req, res);
                pc.update(showPost);
            }
        }
    }

    public List<Post> getSimilarPosts(Post showPost, Pager pager) {
        List<Post> similarquestions = Collections.emptyList();
        if (!showPost.isReply()) {
            String likeTxt = Utils.abbreviate(Utils.stripAndTrim((showPost.getTitle() + " " + showPost.getBody())),
                    2000);
            if (!StringUtils.isBlank(likeTxt)) {
                similarquestions = pc.findSimilar(showPost.getType(), showPost.getId(),
                        new String[] { "properties.title", "properties.body", "properties.tags" }, likeTxt, pager);
            }
        }
        return similarquestions;
    }

    public boolean param(HttpServletRequest req, String param) {
        return req.getParameter(param) != null;
    }

    public boolean isAjaxRequest(HttpServletRequest req) {
        return req.getHeader("X-Requested-With") != null || req.getParameter("X-Requested-With") != null;
    }

    public boolean isAdmin(Profile authUser) {
        return authUser != null && User.Groups.ADMINS.toString().equals(authUser.getGroups());
    }

    public boolean isMod(Profile authUser) {
        return authUser != null && (isAdmin(authUser) || User.Groups.MODS.toString().equals(authUser.getGroups()));
    }

    public boolean isRecognizedAsAdmin(User u) {
        return u.isAdmin() || ADMINS.contains(u.getIdentifier()) || ADMINS.contains(u.getEmail());
    }

    public boolean canComment(Profile authUser, HttpServletRequest req) {
        return isAuthenticated(req) && (authUser.hasBadge(ENTHUSIAST)
                || Config.getConfigBoolean("new_users_can_comment", true) || isMod(authUser));
    }

    public boolean canAccessSpace(Profile authUser, String targetSpaceId) {
        if (authUser == null) {
            return isDefaultSpacePublic();
        }
        if (StringUtils.isBlank(targetSpaceId)) {
            // can user access the default space (blank)
            return isDefaultSpacePublic() || isMod(authUser) || !authUser.hasSpaces();
        }
        boolean isMemberOfSpace = false;
        for (String space : authUser.getSpaces()) {
            if (StringUtils.startsWithIgnoreCase(space, getSpaceId(targetSpaceId) + ":")) {
                isMemberOfSpace = true;
                break;
            }
        }
        return isMemberOfSpace;
    }

    public String getValidSpaceId(Profile authUser, String space) {
        if (authUser == null) {
            return "";
        }
        String defaultSpace = authUser.hasSpaces() ? authUser.getSpaces().get(0) : "";
        String s = canAccessSpace(authUser, space) ? space : defaultSpace;
        return s == null ? "" : s;
    }

    public String getSpaceName(String space) {
        return RegExUtils.replaceAll(space, "^scooldspace:[^:]+:", "");
    }

    public String getSpaceId(String space) {
        String s = StringUtils.contains(space, ":") ? StringUtils.substring(space, 0, space.lastIndexOf(":")) : "";
        return "scooldspace".equals(s) ? space : s;
    }

    public String getSpaceFilteredQuery(HttpServletRequest req) {
        Profile authUser = getAuthUser(req);
        String currentSpace = getValidSpaceId(authUser, getCookieValue(req, SPACE_COOKIE));
        return StringUtils.isBlank(currentSpace) ? (canAccessSpace(authUser, currentSpace) ? "*" : "")
                : "properties.space:\"" + currentSpace + "\"";
    }

    public String sanitizeQueryString(String query, HttpServletRequest req) {
        String qf = getSpaceFilteredQuery(req);
        String defaultQuery = "*";
        String q = StringUtils.trimToEmpty(query);
        if (qf.isEmpty() || qf.length() > 1) {
            q = q.replaceAll("[\\*\\?]", "").trim();
            q = RegExUtils.removeAll(q, "AND");
            q = RegExUtils.removeAll(q, "OR");
            q = RegExUtils.removeAll(q, "NOT");
            q = q.trim();
            defaultQuery = "";
        }
        if (qf.isEmpty()) {
            return defaultQuery;
        } else if ("*".equals(qf)) {
            return q;
        } else {
            if (q.isEmpty()) {
                return qf;
            } else {
                return qf + " AND " + q;
            }
        }
    }

    public boolean isMine(Post showPost, Profile authUser) {
        // author can edit, mods can edit & ppl with rep > 100 can edit
        return showPost != null && authUser != null ? authUser.getId().equals(showPost.getCreatorid()) : false;
    }

    public boolean canEdit(Post showPost, Profile authUser) {
        return authUser != null ? (authUser.hasBadge(TEACHER) || isMod(authUser) || isMine(showPost, authUser))
                : false;
    }

    public <P extends ParaObject> P populate(HttpServletRequest req, P pobj, String... paramName) {
        if (pobj != null && paramName != null) {
            HashMap<String, Object> data = new HashMap<String, Object>();
            for (String param : paramName) {
                String[] values;
                if (param.matches(".+?\\|.$")) {
                    // convert comma-separated value to list of strings
                    String cleanParam = param.substring(0, param.length() - 2);
                    values = req.getParameterValues(cleanParam);
                    String firstValue = (values != null && values.length > 0) ? values[0] : null;
                    String separator = param.substring(param.length() - 1);
                    if (!StringUtils.isBlank(firstValue)) {
                        data.put(cleanParam, Arrays.asList(firstValue.split(separator)));
                    }
                } else {
                    values = req.getParameterValues(param);
                    String firstValue = (values != null && values.length > 0) ? values[0] : null;
                    if (values != null && values.length > 1) {
                        data.put(param, Arrays.asList(values));
                    } else if (firstValue != null) {
                        data.put(param, firstValue);
                    }
                }
            }
            if (!data.isEmpty()) {
                ParaObjectUtils.setAnnotatedFields(pobj, data, null);
            }
        }
        return pobj;
    }

    public <P extends ParaObject> Map<String, String> validate(P pobj) {
        HashMap<String, String> error = new HashMap<String, String>();
        if (pobj != null) {
            Set<ConstraintViolation<P>> errors = ValidationUtils.getValidator().validate(pobj);
            for (ConstraintViolation<P> err : errors) {
                error.put(err.getPropertyPath().toString(), err.getMessage());
            }
        }
        return error;
    }

    public String getGravatar(String email) {
        if (email == null) {
            return "https://www.gravatar.com/avatar?d=retro&size=400";
        }
        return "https://www.gravatar.com/avatar/" + Utils.md5(email.toLowerCase()) + "?size=400&d=retro";
    }

    public String getGravatar(Profile profile) {
        if (profile == null || profile.getUser() == null) {
            return "https://www.gravatar.com/avatar?d=retro&size=400";
        } else {
            return getGravatar(profile.getUser().getEmail());
        }
    }

    public void clearSession(HttpServletRequest req, HttpServletResponse res) {
        if (req != null) {
            HttpSession session = req.getSession(false);
            if (session != null) {
                session.invalidate();
            }
            HttpUtils.removeStateParam(Config.AUTH_COOKIE, req, res);
            HttpUtils.removeStateParam(CSRF_COOKIE, req, res);
        }
    }

    public boolean addBadgeOnce(Profile authUser, Profile.Badge b, boolean condition) {
        return addBadge(authUser, b, condition && !authUser.hasBadge(b), false);
    }

    public boolean addBadgeOnceAndUpdate(Profile authUser, Profile.Badge b, boolean condition) {
        return addBadgeAndUpdate(authUser, b, condition && authUser != null && !authUser.hasBadge(b));
    }

    public boolean addBadgeAndUpdate(Profile authUser, Profile.Badge b, boolean condition) {
        return addBadge(authUser, b, condition, true);
    }

    public boolean addBadge(Profile user, Profile.Badge b, boolean condition, boolean update) {
        if (user != null && condition) {
            String newb = StringUtils.isBlank(user.getNewbadges()) ? "" : user.getNewbadges().concat(",");
            newb = newb.concat(b.toString());

            user.addBadge(b);
            user.setNewbadges(newb);
            if (update) {
                user.update();
                return true;
            }
        }
        return false;
    }

    public List<String> checkForBadges(Profile authUser, HttpServletRequest req) {
        List<String> badgelist = new ArrayList<String>();
        if (authUser != null && !isAjaxRequest(req)) {
            long oneYear = authUser.getTimestamp() + (365 * 24 * 60 * 60 * 1000);
            addBadgeOnce(authUser, Profile.Badge.ENTHUSIAST, authUser.getVotes() >= ENTHUSIAST_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.FRESHMAN, authUser.getVotes() >= FRESHMAN_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.SCHOLAR, authUser.getVotes() >= SCHOLAR_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.TEACHER, authUser.getVotes() >= TEACHER_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.PROFESSOR, authUser.getVotes() >= PROFESSOR_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.GEEK, authUser.getVotes() >= GEEK_IFHAS);
            addBadgeOnce(authUser, Profile.Badge.SENIOR,
                    (System.currentTimeMillis() - authUser.getTimestamp()) >= oneYear);

            if (!StringUtils.isBlank(authUser.getNewbadges())) {
                badgelist.addAll(Arrays.asList(authUser.getNewbadges().split(",")));
                authUser.setNewbadges(null);
                authUser.update();
            }
        }
        return badgelist;
    }

    public String loadEmailTemplate(String name) {
        if (name == null) {
            return "";
        }
        if (EMAIL_TEMPLATES.containsKey(name)) {
            return EMAIL_TEMPLATES.get(name);
        }
        String template = "";
        InputStream in = getClass().getClassLoader().getResourceAsStream("emails/" + name + ".html");
        if (in != null) {
            try (Scanner s = new Scanner(in).useDelimiter("\\A")) {
                template = s.hasNext() ? s.next() : "";
                if (!StringUtils.isBlank(template)) {
                    EMAIL_TEMPLATES.put(name, template);
                }
            } catch (Exception ex) {
                logger.info("Couldn't load email template '{0}'. - {1}", name, ex.getMessage());
            } finally {
                try {
                    in.close();
                } catch (IOException ex) {
                    logger.error(null, ex);
                }
            }
        }
        return template;
    }

    public void setSecurityHeaders(HttpServletRequest request, HttpServletResponse response) {
        // CSP Header
        if (Config.getConfigBoolean("csp_header_enabled", true)) {
            response.addHeader("Content-Security-Policy",
                    Config.getConfigParam("csp_header", getDefaultContentSecurityPolicy(request.isSecure())));
        }
        // HSTS Header
        if (Config.getConfigBoolean("hsts_header_enabled", true)) {
            response.addHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains");
        }
        // Frame Options Header
        if (Config.getConfigBoolean("framing_header_enabled", true)) {
            response.addHeader("X-Frame-Options", "SAMEORIGIN");
        }
        // XSS Header
        if (Config.getConfigBoolean("xss_header_enabled", true)) {
            response.addHeader("X-XSS-Protection", "1; mode=block");
        }
        // Content Type Header
        if (Config.getConfigBoolean("contenttype_header_enabled", true)) {
            response.addHeader("X-Content-Type-Options", "nosniff");
        }
        // Referrer Header
        if (Config.getConfigBoolean("referrer_header_enabled", true)) {
            response.addHeader("Referrer-Policy", "strict-origin");
        }
    }

    public String getDefaultContentSecurityPolicy(boolean isSecure) {
        return (isSecure ? "upgrade-insecure-requests; " : "") + "default-src 'self'; " + "base-uri 'self'; "
                + "form-action 'self'; "
                + "connect-src 'self' scoold.com www.google-analytics.com www.googletagmanager.com; "
                + "frame-src 'self' accounts.google.com staticxx.facebook.com; "
                + "font-src cdnjs.cloudflare.com fonts.gstatic.com fonts.googleapis.com; "
                + "script-src 'self' 'unsafe-eval' apis.google.com maps.googleapis.com connect.facebook.net "
                + "cdnjs.cloudflare.com www.google-analytics.com www.googletagmanager.com code.jquery.com static.scoold.com; "
                + "style-src 'self' 'unsafe-inline' fonts.googleapis.com cdnjs.cloudflare.com static.scoold.com; "
                + "img-src 'self' https: data:; " + "report-uri /reports/cspv";
    }
}