Package com.google.testing.testify.risk.frontend.server.service.impl

Source Code of com.google.testing.testify.risk.frontend.server.service.impl.UserServiceImpl

// Copyright 2010 Google Inc. All Rights Reseved.
//
// 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.google.testing.testify.risk.frontend.server.service.impl;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.api.utils.SystemProperty;
import com.google.appengine.api.utils.SystemProperty.Environment.Value;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.testing.testify.risk.frontend.model.LoginStatus;
import com.google.testing.testify.risk.frontend.model.Project;
import com.google.testing.testify.risk.frontend.model.UserInfo;
import com.google.testing.testify.risk.frontend.server.service.UserService;
import com.google.testing.testify.risk.frontend.shared.rpc.UserRpc.ProjectAccess;

import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

/**
* Implementation of UserService. Returns user and security information.
*
* @author jimr@google.com (Jim Reardon)
*/
@Singleton
public class UserServiceImpl implements UserService {

  private static final String LOCAL_DOMAIN =
      System.getProperty("com.google.testing.testify.risk.frontend.localdomain");
  private static final boolean WHITELISTING_ENABLED =
      Boolean.valueOf(System.getProperty("com.google.testing.testify.risk.frontend.whitelisting"));

  private static final Logger log = Logger.getLogger(UserServiceImpl.class.getName());
  private final PersistenceManagerFactory pmf;
  private final com.google.appengine.api.users.UserService userService;

  @Inject
  public UserServiceImpl(PersistenceManagerFactory pmf) {
    this.pmf = pmf;
    // TODO(jimr): Inject this.
    this.userService = UserServiceFactory.getUserService();
  }

  @Override
  public boolean isUserLoggedIn() {
    return getEmail() != null;
  }

  @Override
  public String getEmail() {
    User user = userService.getCurrentUser();
    return user == null ? null : user.getEmail();
  }

  @Override
  public boolean isWhitelistingEnabled() {
    return WHITELISTING_ENABLED;
  }

  @Override
  public boolean isWhitelisted() {
    if (isInternalUser()) {
      return true;
    }
    UserInfo user = getCurrentUserInfo(pmf.getPersistenceManager(), false);
    if (user == null) {
      return false;
    }
    return user.getIsWhitelisted();
  }

  @Override
  public boolean isInternalUser() {
    if (isDevMode()) {
      return true;
    }
    String email = getEmail();
    if (email == null || LOCAL_DOMAIN == null) {
      return false;
    }
    return email.endsWith(LOCAL_DOMAIN);
  }

  @Override
  public LoginStatus getLoginStatus(String returnUrl) {
    User user = userService.getCurrentUser();
    String email = null;
    String url;

    if (user == null) {
      email = "";
      url = userService.createLoginURL(returnUrl);
    } else {
      email = user.getEmail();
      url = userService.createLogoutURL(returnUrl);
    }
    return new LoginStatus(user != null, url, email);
  }

  @Override
  public boolean hasAdministratorAccess() {
    return userService.isUserAdmin();
  }

  @Override
  public boolean hasViewAccess(long projectId) {
    return hasAccess(ProjectAccess.VIEW_ACCESS, projectId);
  }

  @Override
  public boolean hasViewAccess(Project project) {
    return hasAccess(ProjectAccess.VIEW_ACCESS, project, getEmail());
  }

  @Override
  public boolean hasEditAccess(long projectId) {
    return hasEditAccess(projectId, getEmail());
  }

  @Override
  public boolean hasEditAccess(Project project) {
    return hasAccess(ProjectAccess.VIEW_ACCESS, project, getEmail());
  }

  @Override
  public boolean hasEditAccess(long projectId, String asEmail) {
    return hasAccess(ProjectAccess.EDIT_ACCESS, projectId, asEmail);
  }

  @Override
  public boolean hasOwnerAccess(long projectId) {
    return hasAccess(ProjectAccess.OWNER_ACCESS, projectId);
  }

  @Override
  public boolean hasAccess(ProjectAccess accessLevel, long projectId) {
    return hasAccess(accessLevel, projectId, getEmail());
  }

  @Override
  public boolean hasAccess(ProjectAccess accessLevel, long projectId, String asEmail) {
    return hasAccess(accessLevel, getProject(projectId), asEmail);
  }

  private boolean hasAccess(ProjectAccess accessLevel, Project project, String asEmail) {
    if (project == null) {
      log.warning("Call to hasAccess with a null project.");
      return false;
    }

    ProjectAccess accessHas = getAccessLevel(project, asEmail);
    log.info("Access has: " + accessHas.name() + " Access desired: " + accessLevel.name());
    return accessHas.hasAccess(accessLevel);
  }

  @Override
  public ProjectAccess getAccessLevel(long projectId) {
    return getAccessLevel(getProject(projectId), getEmail());
  }

  @Override
  public ProjectAccess getAccessLevel(Project project) {
    return getAccessLevel(project, getEmail());
  }

  @Override
  public ProjectAccess getAccessLevel(long projectId, String asEmail) {
    return getAccessLevel(getProject(projectId), asEmail);
  }

  private ProjectAccess getAccessLevel(Project project, String asEmail) {
    if (project == null) {
      log.warning("Call to getAccessLevel with a null project.");
      return ProjectAccess.NO_ACCESS;
    }

    if (asEmail == null) {
      if (project.getIsPubliclyVisible()) {
        return ProjectAccess.VIEW_ACCESS;
      } else {
        return ProjectAccess.NO_ACCESS;
      }
    } else {
      if (hasAdministratorAccess()) {
        return ProjectAccess.ADMINISTRATOR_ACCESS;
      } else if (project.getProjectOwners().contains(asEmail)) {
        return ProjectAccess.OWNER_ACCESS;
      } else if (project.getProjectEditors().contains(asEmail)) {
        return ProjectAccess.EDIT_ACCESS;
      } else if (project.getProjectViewers().contains(asEmail)) {
        return ProjectAccess.EXPLICIT_VIEW_ACCESS;
      } else if (project.getIsPubliclyVisible()) {
        return ProjectAccess.VIEW_ACCESS;
      } else {
        return ProjectAccess.NO_ACCESS;
      }
    }
  }

  @Override
  public List<Long> getStarredProjects() {
    log.info("Getting starred projects for current user.");

    PersistenceManager pm = pmf.getPersistenceManager();
    List<Long> starredProjects = Lists.newArrayList();
    try {
      UserInfo userInfo = getCurrentUserInfo(pm, true);

      // Copy list items over since we cannot return the server-side list type to client-side code.
      if (userInfo != null) {
        for (long projectId : userInfo.getStarredProjects()) {
          starredProjects.add(projectId);
        }
      }
    } finally  {
      pm.close();
    }

    return starredProjects;
  }

  @Override
  public void starProject(long projectId) {
    log.info("Starring project: " + projectId);

    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      UserInfo userInfo = getCurrentUserInfo(pm, true);
      if (userInfo != null) {
        userInfo.starProject(projectId);
        pm.makePersistent(userInfo);
      }
    } finally  {
      pm.close();
    }
  }

  @Override
  public void unstarProject(long projectId) {
    log.info("Unstarring project: " + projectId);

    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      UserInfo userInfo = getCurrentUserInfo(pm, true);
      if (userInfo != null) {
        userInfo.unstarProject(projectId);
        pm.makePersistent(userInfo);
      }
    } finally  {
      pm.close();
    }
  }

  @Override
  public boolean isDevMode() {
    Value env = SystemProperty.environment.value();
    log.info("System environment: " + env.toString());
    return env.equals(SystemProperty.Environment.Value.Development);
  }

  /**
   * Returns all information Testify knows about the currently logged in user. If the logged in user
   * is not currently in Testify, a new UserInfo entry will be created. Also, will return null if
   * the user is not currently logged in.
   *
   * @param pm The PersistenceManager session for which the UserInfo object was returned.
   */
  private UserInfo getCurrentUserInfo(PersistenceManager pm, boolean createIfMissing) {
    User appEngineUser = userService.getCurrentUser();

    if (appEngineUser == null) {
      log.info("Unable to get user info. User is not logged in.");
      return null;
    }

    // If they are logged in, get the Testify UserInfo record on file. If unavailable, create a new
    // entry.
    String loggedInUserId = appEngineUser.getUserId();
    String currentEmail = appEngineUser.getEmail();

    Query jdoQuery = pm.newQuery(UserInfo.class);
    jdoQuery.declareParameters("String userIdParam");
    jdoQuery.setFilter("userId == userIdParam");

    log.info("Querying for user " + currentEmail + " by id " + loggedInUserId);
    UserInfo user = queryAndReturnFirst(jdoQuery, loggedInUserId);
    if (user != null) {
      // Update email address if missing or different.
      if (!currentEmail.equals(user.getCurrentEmail())) {
        log.info("Adding or updating email for " + currentEmail + "  id " + loggedInUserId);
        user.setCurrentEmail(currentEmail);
        pm.makePersistent(user);
      }
    } else {
      // Try to find by email instead.
      log.info("Querying for user " + currentEmail + " by email instead.");
      jdoQuery = pm.newQuery(UserInfo.class);
      jdoQuery.declareParameters("String currentEmailParam");
      jdoQuery.setFilter("currentEmail == currentEmailParam");

      user = queryAndReturnFirst(jdoQuery, currentEmail);
      if (user != null) {
        // Add the user's user ID since we now know it.
        if (user.getUserId() == null || user.getUserId().equals("")) {
          log.info("Adding user ID for " + currentEmail + ".");
          user.setUserId(appEngineUser.getUserId());
          pm.makePersistent(user);
        } else {
          log.severe("Found a user by email but user ID was set to a different ID.");
          user = null;
        }
      }
    }
    if (user == null) {
      log.info("Tried to get info for " + loggedInUserId + " but no entry was found.");
      if (createIfMissing) {
        log.info("Creating new UserInfo for user: " + loggedInUserId);
        user = new UserInfo();
        user.setUserId(loggedInUserId);
        user.setCurrentEmail(currentEmail);
        pm.makePersistent(user);
      }
    }
    return user;
  }

  @SuppressWarnings("unchecked")
  private UserInfo queryAndReturnFirst(Query query, String param) {
    List<UserInfo> users = (List<UserInfo>) query.execute(param);
    if (users.size() > 0) {
      return users.get(0);
    }
    return null;
  }

  /**
   * Loads a project.  This isn't done using ProjectServiceImpl because it would create a circular
   * dependency.
   *
   * @param id projectId to load.
   * @return the loaded project.
   */
  private Project getProject(long id) {
    // TODO(jimr): To reduce this code duplication, project loading should be done at a lower level
    // so that object can be injected both here and into project service.
    log.info("Getting project: " + Long.toString(id));

    PersistenceManager pm = pmf.getPersistenceManager();
    try {
      return pm.getObjectById(Project.class, id);
    } finally {
      pm.close();
    }
  }
}
TOP

Related Classes of com.google.testing.testify.risk.frontend.server.service.impl.UserServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.