Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.formkiq.server.service.FolderServiceImpl Maven / Gradle / Ivy
/*
* 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.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
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 java.util.zip.ZipOutputStream;
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.FolderFormsListDTO;
import com.formkiq.server.domain.type.FolderListDTO;
import com.formkiq.server.domain.type.FolderPermission;
import com.formkiq.server.domain.type.FormDTO;
import com.formkiq.server.domain.type.SyncListDTO;
import com.formkiq.server.domain.type.UserRole;
import com.formkiq.server.service.dto.ArchiveDTO;
import com.formkiq.server.service.dto.Workflow;
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 UUID}
* @param uuid {@link String}
* @return {@link Pair}
*/
private Pair checkFormSavePermissions(
final User user, final String folder, final UUID 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 (parentuuid != null && !this.securityService
.hasPermission(accessForm, FolderPermission.PERM_FORM_ENTRY)) {
throw new FormAccessDeniedException();
}
if (parentuuid == null && !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) {
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.hasFormChildren(folder, uuid)) {
this.folderDao.deleteForm(folder, uuid);
} 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;
}
@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) {
throw new FormNotFoundException("Folder not found");
}
return dto;
}
@Override
public byte[] findFormData(final String client, final String uuid)
throws IOException {
Map map = new HashMap();
Object[] obj = findFormDataInternal(client, uuid);
byte[] data = (byte[]) obj[0];
map.put(uuid, data);
FolderForm clientForm = (FolderForm) obj[1];
if (ClientFormType.WORKFLOW.equals(clientForm.getType())) {
Workflow workflow = this.jsonMapper.build()
.readValue(clientForm.getData(), Workflow.class);
for (String formUUID : workflow.getSteps()) {
obj = findFormDataInternal(client, formUUID);
byte[] formdata = (byte[]) obj[0];
map.put(formUUID, formdata);
}
}
if (map.size() > 1) {
return zipFile(map);
}
return map.values().iterator().next();
}
/**
* 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 token) {
return this.folderDao.findForms(folder, token);
}
@Override
public FolderFormsListDTO findForms(final String folder,
final String form, final String token) {
return this.folderDao.findForms(folder, form, token);
}
@Override
public FolderListDTO getFolderList(final UserDetails ud,
final String token) {
User user = (User) ud;
return this.folderDao.findFolderList(user, token);
}
@Override
public SyncListDTO getSyncList(final UserDetails ud,
final ClientFormType type, final String folder,
final String nextToken) {
User user = (User) ud;
FolderAccess fa = this.folderDao.findFolderAccess(user, folder);
if (this.securityService.hasPermission(fa,
FolderPermission.PERM_FORM_RESULTS)) {
return this.folderDao.findFormSyncList(type, folder, nextToken);
}
throw new FormAccessDeniedException();
}
@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.setFolderid(f.getFolderid());
fa.setUserid(user.getUserid());
fa.setPermissions(Arrays.asList(FolderPermission.PERM_FORM_ADMIN));
this.folderDao.saveFolderAccess(fa);
return f.getFolderid();
}
/**
* Saves Form.
* @param archive {@link ArchiveDTO}
* @param folderForm {@link FolderForm}
* @param folder {@link String}
* @param bytes byte[]
*/
private void saveForm(final ArchiveDTO archive, final FolderForm folderForm,
final String folder, final byte[] bytes) {
UUID uuid = archive.getUUID();
UUID parentuuid = archive.getParentUUID();
ClientFormType type = archive.isFormJSON() ? ClientFormType.FORM
: ClientFormType.WORKFLOW;
String data = archive.getData();
Date insertedDate = archive.getInsertedDate();
Date updatedDate = archive.getUpdatedDate();
folderForm.setType(type);
folderForm.setFolderid(UUID.fromString(folder));
folderForm.setUUID(uuid);
folderForm.setData(data);
folderForm.setInsertedDate(insertedDate);
folderForm.setUpdatedDate(updatedDate);
folderForm.setParentUUID(parentuuid);
updateAsset(folderForm, bytes);
this.folderDao.saveForm(folderForm);
}
@Override
public String saveForm(final UserDetails ud,
final String folder,
final byte[] bytes, final String lastSha1hash) {
User user = (User) ud;
boolean isAdmin = UserRole.ROLE_ADMIN.equals(user.getRole());
ArchiveDTO archive = extractJSONFromZipFile(bytes);
String uuid = archive.getUUID().toString();
String name = archive.getName();
UUID parentuuid = archive.getParentUUID();
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 (!isAdmin || StringUtils.hasText(lastSha1hash)) {
if (!StringUtils.hasText(lastSha1hash)) {
throw new FormNotFoundException("sha1hash parameter required");
}
if (!lastSha1hash.equals(folderForm.getSha1hash())) {
throw new FormNotFoundException(name
+ " has been modified. 'Sync' first and try again.");
}
}
saveForm(archive, folderForm, folder, bytes);
return folderForm.getSha1hash();
}
/**
* Update Asset on FolderForm.
* @param form {@link FolderForm}
* @param bytes byte[]
*/
private void updateAsset(final FolderForm form, final byte[] bytes) {
Asset asset = null;
UUID assetid = form.getAssetid();
if (assetid != null) {
asset = this.assetDao.findAsset(assetid);
}
if (asset == null) {
asset = new Asset();
}
asset.setData(this.userDao.convertToBlob(bytes));
asset = this.assetDao.saveAsset(asset);
form.setAssetid(asset.getAssetId());
form.setSha1hash(DigestUtils.sha1Hex(bytes));
}
/**
* Create Zip file.
* @param map {@link Map}
* @return byte[] zip file
* @throws IOException IOException
*/
private byte[] zipFile(final Map map) throws IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(bs);
for (Map.Entry e : map.entrySet()) {
String name = e.getKey();
byte[] data = e.getValue();
ZipEntry ze = new ZipEntry(name + ".zip");
zip.putNextEntry(ze);
zip.write(data, 0, data.length);
zip.closeEntry();
}
byte[] bytes = bs.toByteArray();
IOUtils.closeQuietly(bs);
IOUtils.closeQuietly(zip);
return bytes;
}
}