io.stallion.forms.SimpleFormEndpoints.java Source code

Java tutorial

Introduction

Here is the source code for io.stallion.forms.SimpleFormEndpoints.java

Source

/*
 * Stallion Core: A Modern Web Framework
 *
 * Copyright (C) 2015 - 2016 Stallion Software LLC.
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 2 of
 * the License, or (at your option) any later version. This program is distributed in the hope that
 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 * License for more details. You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 *
 *
 *
 */

package io.stallion.forms;

import io.stallion.exceptions.ClientException;
import io.stallion.requests.validators.SafeMerger;
import io.stallion.restfulEndpoints.ObjectParam;
import io.stallion.services.LocalMemoryCache;
import io.stallion.utils.Encrypter;
import org.apache.commons.lang3.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import static io.stallion.utils.Literals.*;
import static io.stallion.Context.*;

public class SimpleFormEndpoints {

    @POST
    @Path("/contacts/submit-form")
    public Boolean submitForm(
            @ObjectParam(targetClass = SimpleFormSubmission.class) SimpleFormSubmission rawSubmission) {
        SimpleFormSubmission submission = SafeMerger.with().nonEmpty("antiSpamToken", "pageUrl", "data")
                .optionalEmail("email").optional("pageTitle", "formId").merge(rawSubmission);

        /* The Anti-spam token is an encrypted token with a milliseconds timestamp and a randomly generated key
           This prevents a spammer from simply hitting this endpoint over and over again with a script. A given
           random key can only be used once within an hour, and all tokens expire after an hour, so all together
           it is not possible to submit more than once.
            
           This will not stop a spammer who is actually requesting a new copy of the page and who is
           parsing out the spam token single every time. We would have to implement IP address throttling or
           captchas to fix that.
         */

        String token = Encrypter.decryptString(settings().getAntiSpamSecret(), submission.getAntiSpamToken());
        if (empty(token) || !token.contains("|")) {
            throw new ClientException("Anti-spam token is not in the correct format");
        }
        String[] parts = StringUtils.split(token, "|", 2);
        Long time = Long.parseLong(parts[0]);
        String randomKey = parts[1];

        if (time == null || ((time + 60 * 60 * 1000) < mils())) {
            throw new ClientException("Anti-spam token has expired. Please reload the page and submit again.");
        }

        Integer submissionCount = or((Integer) LocalMemoryCache.get("form_submissions", randomKey), 0);
        if (submissionCount > 0) {
            throw new ClientException("You have already submitted this form once.");
        }

        submission.setSubmittedAt(mils());
        SimpleFormSubmissionController.instance().save(submission);
        if (!empty(submission.getEmail())) {
            SimpleFormSubmissionEmailTask.enqueue(submission);
        }

        // Store a record of this token, so it cannot be reused
        LocalMemoryCache.set("form_submissions", randomKey, submissionCount + 1, 90 * 60 * 1000);

        return true;
    }
}