org.codice.ddf.catalog.ui.security.app.UserApplication.java Source code

Java tutorial

Introduction

Here is the source code for org.codice.ddf.catalog.ui.security.app.UserApplication.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>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 Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package org.codice.ddf.catalog.ui.security.app;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.codice.gsonsupport.GsonTypeAdapters.MAP_STRING_TO_OBJECT_TYPE;
import static spark.Spark.exception;
import static spark.Spark.get;
import static spark.Spark.put;

import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ddf.security.Subject;
import ddf.security.SubjectIdentity;
import ddf.security.SubjectUtils;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.codice.ddf.catalog.ui.metacard.EntityTooLargeException;
import org.codice.ddf.catalog.ui.security.Constants;
import org.codice.ddf.catalog.ui.util.EndpointUtil;
import org.codice.ddf.persistence.PersistenceException;
import org.codice.ddf.persistence.PersistentItem;
import org.codice.ddf.persistence.PersistentStore;
import org.codice.ddf.persistence.PersistentStore.PersistenceType;
import org.codice.gsonsupport.GsonTypeAdapters.LongDoubleTypeAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spark.servlet.SparkApplication;

public class UserApplication implements SparkApplication {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserApplication.class);

    private static final Gson GSON = new GsonBuilder().disableHtmlEscaping()
            .registerTypeAdapterFactory(LongDoubleTypeAdapter.FACTORY).create();

    private final EndpointUtil util;

    private final PersistentStore persistentStore;

    private final SubjectIdentity subjectIdentity;

    public UserApplication(EndpointUtil util, PersistentStore persistentStore, SubjectIdentity subjectIdentity) {
        this.util = util;
        this.persistentStore = persistentStore;
        this.subjectIdentity = subjectIdentity;
    }

    @Override
    public void init() {
        get("/user", (req, res) -> {
            Subject subject = (Subject) SecurityUtils.getSubject();
            res.type(APPLICATION_JSON);
            return getSubjectAttributes(subject);
        }, util::getJson);

        put("/user/preferences", APPLICATION_JSON, (req, res) -> {
            Subject subject = (Subject) SecurityUtils.getSubject();

            if (subject.isGuest()) {
                res.status(401);
                return ImmutableMap.of("message", "Guest cannot save preferences.");
            }

            Map<String, Object> preferences = GSON.fromJson(util.safeGetBody(req), MAP_STRING_TO_OBJECT_TYPE);

            if (preferences == null) {
                preferences = new HashMap<>();
            }

            setUserPreferences(subject, preferences);

            return preferences;
        }, util::getJson);

        exception(EntityTooLargeException.class, util::handleEntityTooLargeException);

        exception(IOException.class, util::handleIOException);

        exception(RuntimeException.class, util::handleRuntimeException);
    }

    private void setUserPreferences(Subject subject, Map<String, Object> preferences) {
        String json = GSON.toJson(preferences);

        LOGGER.trace("preferences JSON text:\n {}", json);

        String userid = subjectIdentity.getUniqueIdentifier(subject);

        LOGGER.trace("Update preferences for: {}", userid);

        PersistentItem item = new PersistentItem();
        item.addIdProperty(userid);
        item.addProperty("user", userid);
        item.addProperty("preferences_json", "_bin",
                Base64.getEncoder().encodeToString(json.getBytes(Charset.defaultCharset())));

        try {
            persistentStore.add(PersistenceType.PREFERENCES_TYPE.toString(), item);
        } catch (PersistenceException e) {
            LOGGER.info("PersistenceException while trying to persist preferences for user {}", userid, e);
        }
    }

    private Set<String> getSubjectRoles(Subject subject) {
        return new TreeSet<>(SubjectUtils.getAttribute(subject, Constants.ROLES_CLAIM_URI));
    }

    private Map getSubjectPreferences(Subject subject) {
        String userid = subjectIdentity.getUniqueIdentifier(subject);

        try {
            String filter = String.format("user = '%s'", userid);
            List<Map<String, Object>> preferencesList = persistentStore
                    .get(PersistenceType.PREFERENCES_TYPE.toString(), filter);
            if (preferencesList.size() == 1) {
                byte[] json = (byte[]) preferencesList.get(0).get("preferences_json_bin");

                return GSON.fromJson(new String(json, Charset.defaultCharset()), MAP_STRING_TO_OBJECT_TYPE);
            }
        } catch (PersistenceException e) {
            LOGGER.info("PersistenceException while trying to retrieve persisted preferences for user {}", userid,
                    e);
        }

        return Collections.emptyMap();
    }

    private Map<String, Object> getSubjectAttributes(Subject subject) {
        // @formatter:off
        Map<String, Object> required = ImmutableMap.of("userid", subjectIdentity.getUniqueIdentifier(subject),
                "username", SubjectUtils.getName(subject), "isGuest", subject.isGuest(), "roles",
                getSubjectRoles(subject), "preferences", getSubjectPreferences(subject));
        // @formatter:on

        String email = SubjectUtils.getEmailAddress(subject);

        if (StringUtils.isEmpty(email)) {
            return required;
        }

        return ImmutableMap.<String, Object>builder().putAll(required).put("email", email).build();
    }
}