
com.formkiq.server.service.FolderServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of formkiq-server Show documentation
Show all versions of formkiq-server Show documentation
Server-side integration for the FormKiQ ios application
/*
* Copyright (C) 2016 FormKiQ Inc.
*
* 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.
*/
package com.formkiq.server.service;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.formkiq.server.dao.AssetDao;
import com.formkiq.server.dao.FolderDao;
import com.formkiq.server.dao.UserDao;
import com.formkiq.server.domain.Asset;
import com.formkiq.server.domain.Folder;
import com.formkiq.server.domain.FolderAccess;
import com.formkiq.server.domain.FolderForm;
import com.formkiq.server.domain.User;
import com.formkiq.server.domain.type.ClientFormType;
import com.formkiq.server.domain.type.FolderDTO;
import com.formkiq.server.domain.type.FolderFormStatus;
import com.formkiq.server.domain.type.FolderFormsListDTO;
import com.formkiq.server.domain.type.FolderListDTO;
import com.formkiq.server.domain.type.FolderPermission;
import com.formkiq.server.domain.type.FolderStatus;
import com.formkiq.server.domain.type.FormDTO;
import com.formkiq.server.domain.type.FormOrderByField;
import com.formkiq.server.domain.type.SortDirection;
import com.formkiq.server.service.dto.ArchiveDTO;
import com.formkiq.server.service.dto.Form;
import com.formkiq.server.service.dto.Workflow;
import com.formkiq.server.util.Zips;
import javassist.bytecode.stackmap.TypeData.ClassName;
/**
* FormService implementation.
*
*/
@Service
public class FolderServiceImpl implements FolderService {
/** Logger. */
protected static final Logger LOG = Logger.getLogger(ClassName.class
.getName());
/** AssetDao. */
@Autowired
private AssetDao assetDao;
/** FolderDao. */
@Autowired
private FolderDao folderDao;
/** JSON Object Mapper. */
@Autowired
private Jackson2ObjectMapperBuilder jsonMapper;
/** SpringSecurityService. */
@Autowired
private SpringSecurityService securityService;
/** UserDao. */
@Autowired
private UserDao userDao;
/**
* Checks Form Save Permissions.
* @param user {@link User}
* @param folder {@link String}
* @param parentuuid {@link String}
* @param uuid {@link String}
* @return {@link Pair}
*/
private Pair checkFormSavePermissions(
final User user, final String folder, final String parentuuid,
final String uuid) {
Pair pair = this.folderDao.findForm(user,
folder, uuid);
FolderForm folderForm = pair.getLeft();
FolderAccess accessForm = pair.getRight();
if (accessForm == null && this.securityService.isAdmin()) {
accessForm = new FolderAccess();
accessForm.setPermissions(
Arrays.asList(FolderPermission.PERM_FORM_ADMIN));
folderForm = this.folderDao.findForm(folder, uuid);
pair = Pair.of(folderForm, accessForm);
}
if (!StringUtils.isEmpty(parentuuid) && !this.securityService
.hasPermission(accessForm, FolderPermission.PERM_FORM_ENTRY)) {
throw new FormAccessDeniedException();
}
if (StringUtils.isEmpty(parentuuid) && !this.securityService
.hasPermission(accessForm, FolderPermission.PERM_FORM_DESIGN)) {
throw new FormAccessDeniedException();
}
return pair;
}
@Override
public void deleteFolder(final UserDetails ud, final String folder) {
User user = (User) ud;
FolderAccess access = this.folderDao.findFolderAccess(user, folder);
if (!this.securityService.hasPermission(access,
FolderPermission.PERM_FORM_ADMIN)) {
throw new FormAccessDeniedException();
}
if (!this.folderDao.hasFiles(folder)) {
this.folderDao.deleteFolder(folder);
} else {
throw new PreconditionFailedException(
"Forms need to be deleted first");
}
}
@Override
public void deleteFolderFile(final UserDetails ud, final String folder,
final String uuid, final boolean isparentuuid) {
User user = (User) ud;
FolderAccess access = this.folderDao.findFolderAccess(user, folder);
if (!this.securityService.hasPermission(access,
FolderPermission.PERM_FORM_ADMIN)) {
throw new FormAccessDeniedException();
}
if (isparentuuid) {
this.folderDao.deleteForm(folder, uuid, isparentuuid);
} else if (!this.folderDao.hasFormChildren(folder, uuid)) {
this.folderDao.deleteForm(folder, uuid, isparentuuid);
} else {
throw new PreconditionFailedException(
"Sub records need to be deleted first");
}
}
/**
* Extracts data from a byte[] zip file.
* @param bytes bytes[]
* @return {@link ArchiveDTO}
*/
private ArchiveDTO extractJSONFromZipFile(final byte[] bytes) {
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ZipInputStream zipStream = new ZipInputStream(is);
ArchiveDTO archive = new ArchiveDTO(this.jsonMapper);
try {
ZipEntry entry = null;
while ((entry = zipStream.getNextEntry()) != null) {
String filename = entry.getName();
String data = IOUtils.toString(zipStream);
if (filename.endsWith(".form")) {
archive.addForm(data);
} else if (filename.endsWith(".workflow")) {
archive.addWorkflow(data);
}
}
} catch (IOException e) {
LOG.log(Level.WARNING, e.getMessage(), e);
throw new InvalidRequestBodyException();
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(zipStream);
}
return archive;
}
@Override
public FolderDTO findFolder(final UserDetails ud, final String folder) {
User user = (User) ud;
FolderDTO dto = this.folderDao.findFolderDTO(user, folder);
if (dto == null) {
throw new FormNotFoundException("Folder not found");
}
return dto;
}
/**
* Finds a Folder File, and checks permissions.
* @param folder {@link String}
* @param uuid {@link String}
* @param name {@link String}
* @param parentuuid {@link String}
* @param lastSha1hash {@link String}
* @return {@link FolderForm}
*/
private FolderForm findFolderFile(final String folder, final String uuid,
final String name, final String parentuuid,
final String lastSha1hash) {
User user = (User) this.securityService.getUserDetails();
Pair pair = checkFormSavePermissions(user,
folder, parentuuid, uuid);
FolderForm folderForm = pair.getLeft();
if (folderForm == null) {
if (this.folderDao.findFolder(folder) == null) {
throw new FormAccessDeniedException();
}
if (!StringUtils.isEmpty(parentuuid)) {
pair = checkFormSavePermissions(user, folder, null,
parentuuid.toString());
if (pair.getLeft() == null) {
throw new FormNotFoundException(
"form " + parentuuid + " not found");
}
}
folderForm = new FolderForm();
} else if (!StringUtils.hasText(lastSha1hash)) {
throw new FormNotFoundException("sha1hash parameter required");
} else if (!lastSha1hash.equals(folderForm.getSha1hash())) {
throw new FormNotFoundException(name
+ " has been modified. 'Sync' first and try again.");
}
return folderForm;
}
@Override
public FormDTO findForm(final UserDetails ud, final String folder,
final String uuid) {
FormDTO dto = null;
User user = (User) ud;
FolderAccess access = this.folderDao.findFolderAccess(user, folder);
if (access != null) {
dto = this.folderDao.findFormDTO(folder, uuid);
}
if (dto == null
|| FolderFormStatus.DELETED.name().equals(dto.getStatus())) {
throw new FormNotFoundException("Folder not found");
}
return dto;
}
@Override
public byte[] findFormData(final String client, final String uuid)
throws IOException {
Object[] obj = findFormDataInternal(client, uuid);
byte[] data = (byte[]) obj[0];
return data;
}
/**
* Finds Form Data.
* @param folder {@link String}
* @param uuid {@link String}
* @return Object[]
* @throws IOException IOException
*/
private Object[] findFormDataInternal(final String folder,
final String uuid) throws IOException {
FolderForm clientForm = this.folderDao.findForm(folder, uuid);
if (clientForm != null) {
byte[] data = this.assetDao.findAssetData(clientForm.getAssetid());
return new Object[] { data, clientForm };
}
throw new FormNotFoundException("form " + uuid + " not found");
}
@Override
public FolderFormsListDTO findForms(final String folder,
final String parentUUID, final String text,
final FormOrderByField orderby, final SortDirection direction,
final List status, final String token) {
User user = (User) this.securityService.getUserDetails();
FolderAccess access = this.folderDao.findFolderAccess(user, folder);
if (access != null) {
return this.folderDao.findForms(folder, parentUUID, text, orderby,
direction, status, token);
}
throw new FormNotFoundException("Folder not found");
}
/**
* Get Folder Form Status.
* @param draft boolean
* @return {@link FolderFormStatus}
*/
private FolderFormStatus getFolderFormStatus(final boolean draft) {
return draft ? FolderFormStatus.DRAFT : FolderFormStatus.ACTIVE;
}
@Override
public FolderListDTO getFolderList(final UserDetails ud,
final String token) {
User user = (User) ud;
return this.folderDao.findFolderList(user, token);
}
@Override
public UUID saveFolder(final UserDetails ud, final String folder,
final String foldername) {
User user = (User) ud;
if (StringUtils.hasText(folder)) {
FolderAccess fa = this.folderDao.findFolderAccess(user, folder);
if (fa != null) {
if (!this.securityService.hasPermission(fa,
FolderPermission.PERM_FORM_ADMIN)) {
throw new FormAccessDeniedException();
}
Folder f = this.folderDao.findFolder(folder);
f.setName(foldername);
this.folderDao.saveFolder(f);
return f.getFolderid();
}
throw new FormNotFoundException(foldername);
}
Folder f = new Folder();
f.setName(foldername);
this.folderDao.saveFolder(f);
FolderAccess fa = new FolderAccess();
fa.setStatus(FolderStatus.ACTIVE);
fa.setFolderid(f.getFolderid());
fa.setUserid(user.getUserid());
fa.setPermissions(Arrays.asList(FolderPermission.PERM_FORM_ADMIN));
this.folderDao.saveFolderAccess(fa);
return f.getFolderid();
}
@Override
public String saveForm(final String folder, final byte[] bytes,
final String lastSha1hash) throws IOException {
String sha1hash = null;
ArchiveDTO archive = extractJSONFromZipFile(bytes);
Workflow wf = archive.getWorkflow();
List forms = new ArrayList<>();
if (wf != null) {
String name = wf.getName();
String uuid = wf.getUUID();
String parentuuid = wf.getParentUUID();
FolderForm form = findFolderFile(folder, uuid, name,
parentuuid, lastSha1hash);
form.setType(ClientFormType.WORKFLOW);
form.setFolderid(UUID.fromString(folder));
form.setUUID(UUID.fromString(uuid));
form.setData(archive.getWorkflowJSON());
form.setInsertedDate(wf.getInsertedDate());
form.setUpdatedDate(wf.getUpdatedDate());
form.setStatus(getFolderFormStatus(wf.isDraft()));
if (StringUtils.hasText(parentuuid)) {
form.setParentUUID(UUID.fromString(parentuuid));
}
forms.add(form);
if (StringUtils.isEmpty(parentuuid)) {
byte[] zipfile = Zips.zipFile(name + ".workflow",
archive.getWorkflowJSON());
updateAsset(form, zipfile, sha1hash);
} else {
updateAsset(form, bytes, null);
}
sha1hash = form.getSha1hash();
this.folderDao.saveForm(form);
}
for (Map.Entry e : archive.getForms().entrySet()) {
Form form = e.getValue();
String name = form.getName();
String uuid = form.getUUID();
String parentuuid = form.getParentUUID();
String data = archive.getFormJSON(uuid);
FolderForm folderForm = findFolderFile(folder, uuid, name,
parentuuid, lastSha1hash);
folderForm.setType(ClientFormType.FORM);
folderForm.setFolderid(UUID.fromString(folder));
folderForm.setUUID(UUID.fromString(uuid));
folderForm.setData(data);
folderForm.setStatus(getFolderFormStatus(form.isDraft()));
folderForm.setInsertedDate(form.getInsertedDate());
folderForm.setUpdatedDate(form.getUpdatedDate());
if (StringUtils.hasText(parentuuid)) {
folderForm.setParentUUID(UUID.fromString(parentuuid));
}
forms.add(folderForm);
if (StringUtils.isEmpty(parentuuid)) {
byte[] zipfile = Zips.zipFile(form.getName() + ".form", data);
updateAsset(folderForm, zipfile, sha1hash);
this.folderDao.saveForm(folderForm);
} else if (archive.getWorkflow() == null) {
updateAsset(folderForm, bytes, null);
this.folderDao.saveForm(folderForm);
} else {
folderForm.setSha1hash(sha1hash);
folderForm.setType(ClientFormType.WORKFLOW_FORM);
this.folderDao.saveForm(folderForm);
}
}
return forms.get(0).getSha1hash();
}
/**
* Update Asset on FolderForm.
* @param form {@link FolderForm}
* @param bytes byte[]
* @param sha1hash {@link String}
*/
private void updateAsset(final FolderForm form, final byte[] bytes,
final String sha1hash) {
Asset asset = null;
UUID assetid = form.getAssetid();
if (assetid != null) {
asset = this.assetDao.findAsset(assetid);
}
if (asset == null) {
asset = new Asset();
}
if (bytes != null) {
asset.setData(this.userDao.convertToBlob(bytes));
asset = this.assetDao.saveAsset(asset);
form.setAssetid(asset.getAssetId());
form.setSha1hash(DigestUtils.sha1Hex(bytes));
}
if (StringUtils.hasText(sha1hash)) {
form.setSha1hash(sha1hash);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy