001/*
002 *  Copyright 2025 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.workspaces.documents;
017
018import java.io.IOException;
019import java.util.HashMap;
020import java.util.Map;
021
022import org.apache.avalon.framework.context.Context;
023import org.apache.avalon.framework.context.ContextException;
024import org.apache.avalon.framework.context.Contextualizable;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.cocoon.components.ContextHelper;
029import org.apache.cocoon.environment.Request;
030import org.apache.commons.lang3.StringUtils;
031
032import org.ametys.core.observation.AsyncObserver;
033import org.ametys.core.observation.Event;
034import org.ametys.core.ui.mail.StandardMailBodyHelper;
035import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder;
036import org.ametys.plugins.explorer.ObservationConstants;
037import org.ametys.plugins.workspaces.WorkspacesHelper;
038import org.ametys.plugins.workspaces.project.ProjectManager;
039import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint;
040import org.ametys.plugins.workspaces.project.objects.Project;
041import org.ametys.runtime.config.Config;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.runtime.i18n.I18nizableTextParameter;
044import org.ametys.web.renderingcontext.RenderingContext;
045import org.ametys.web.renderingcontext.RenderingContextHandler;
046
047import jakarta.mail.MessagingException;
048
049/**
050 * Observer to send mails to manager if the workspace space is almost full or full
051 */
052public class SendMailOnFileManagerStorageSpaceLimitreachedObserver implements AsyncObserver, Serviceable, Contextualizable
053{
054    /** The documents module DAO */
055    protected WorkspaceExplorerResourceDAO _workspaceExplorerResourceDAO;
056    
057    /** Project manager */
058    protected ProjectManager _projectManager;
059    
060    /** The workspaces helper */
061    protected WorkspacesHelper _workspaceHelper;
062    
063    /** The document module */
064    protected DocumentWorkspaceModule _documentModule;
065    
066    /** The context */
067    protected Context _context;
068
069    /** The rendering context handler */
070    protected RenderingContextHandler _renderingContextHandler;
071
072    public void service(ServiceManager manager) throws ServiceException
073    {
074        _workspaceExplorerResourceDAO = (WorkspaceExplorerResourceDAO) manager.lookup(WorkspaceExplorerResourceDAO.ROLE);
075        _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE);
076        _workspaceHelper = (WorkspacesHelper) manager.lookup(WorkspacesHelper.ROLE);
077
078        WorkspaceModuleExtensionPoint moduleManagerEP = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE);
079        _documentModule = moduleManagerEP.getModule(DocumentWorkspaceModule.DOCUMENT_MODULE_ID);
080        _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE);
081    }
082    
083    public void contextualize(Context context) throws ContextException
084    {
085        _context = context;
086    }
087    
088    public boolean supports(Event event)
089    {
090        return ObservationConstants.EVENT_RESOURCE_CREATED.equals(event.getId());
091    }
092
093    public int getPriority()
094    {
095        return Integer.MAX_VALUE;
096    }
097
098    public void observe(Event event, Map<String, Object> transientVars) throws Exception
099    {
100        String parenIt = (String) event.getArguments().get(ObservationConstants.ARGS_PARENT_ID);
101
102        Long storageSpaceLimit = _workspaceExplorerResourceDAO.getStorageSpaceLimit();
103        Project project = _projectManager.getParentProject(parenIt);
104        Long usedStorageSpace = _workspaceExplorerResourceDAO.getUsedStorageSpaceByProject(project);
105
106        if (storageSpaceLimit != null && usedStorageSpace >= storageSpaceLimit)
107        {
108            _sendMail(project, true); // Send mail for 100% reached
109            return; // return, as we do not want to send the 95% mail as well
110        }
111
112        if (storageSpaceLimit != null && usedStorageSpace >= (storageSpaceLimit * 0.95))
113        {
114            _sendMail(project, false); // Send mail for 95% reached
115        }
116        
117    }
118
119    private void _sendMail(Project project, boolean isFull) throws MessagingException, IOException
120    {
121        String part = isFull ? "FULL" : "ALMOST_FULL";
122
123        String mailFrom = Config.getInstance().getValue("smtp.mail.from");
124        
125        Map<String, I18nizableTextParameter> params = new HashMap<>();
126        params.put("project", new I18nizableText(project.getTitle()));
127        params.put("projectTitle", new I18nizableText(project.getTitle()));
128        params.put("projectUrl", new I18nizableText(_projectManager.getProjectUrl(project, StringUtils.EMPTY)));
129        
130        String url = _getModuleURL(project);
131        
132        MailBodyBuilder htmlBodyBuilder = StandardMailBodyHelper.newHTMLBody()
133            .withTitle(new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STORAGE_SPACE_" + part + "_MANAGER_MAIL_TITLE", params))
134            .withMessage(new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STORAGE_SPACE_" + part + "_MANAGER_MAIL_BODY_HTML", params))
135            .withLink(url, new I18nizableText("plugin.workspaces", "PROJECT_MAIL_NOTIFICATION_BODY_DEFAULT_BUTTON_TEXT"));
136        
137        I18nizableText i18nSubject = new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STORAGE_SPACE_" + part + "_MANAGER_MAIL_SUBJECT", params);
138        I18nizableText i18nTextBody = new I18nizableText("plugin.workspaces", "PLUGINS_WORKSPACES_STORAGE_SPACE_" + part + "_MANAGER_MAIL_BODY_TEXT", params);
139        _workspaceHelper.sendMailToManagers(project, mailFrom, i18nSubject, htmlBodyBuilder, i18nTextBody);
140    }
141
142    private String _getModuleURL(Project project)
143    {
144        Request request = ContextHelper.getRequest(_context);
145        request.setAttribute("forceAbsoluteUrl", true);
146        RenderingContext currentContext = _renderingContextHandler.getRenderingContext();
147        _renderingContextHandler.setRenderingContext(RenderingContext.FRONT);
148        String url = null;
149        try
150        {
151            url = _documentModule.getModuleUrl(project);
152        }
153        finally
154        {
155            _renderingContextHandler.setRenderingContext(currentContext);
156        }
157        return url;
158    }
159
160}