// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.server.storage;
import com.google.appinventor.shared.rpc.BlocksTruncatedException;
import com.google.appinventor.shared.rpc.Motd;
import com.google.appinventor.shared.rpc.Nonce;
import com.google.appinventor.shared.rpc.admin.AdminUser;
import com.google.appinventor.shared.rpc.AdminInterfaceException;
import com.google.appinventor.shared.rpc.project.Project;
import com.google.appinventor.shared.rpc.project.ProjectSourceZip;
import com.google.appinventor.shared.rpc.project.UserProject;
import com.google.appinventor.shared.rpc.user.User;
import com.google.appinventor.shared.rpc.user.SplashConfig;
import java.io.InputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
/**
* Interface of methods to simplify access to the storage systems.
*
* In all of the methods below that take a user id, it should be a string
* that uniquely identifies the logged-in user and will continue to do so
* indefinitely. It is up to the caller to choose the source of user ids.
*
*/
public interface StorageIo {
/**
* Constant for an invalid project ID.
*/
public static final long INVALID_PROJECTID = 0;
// User management
/**
* Returns user data given user id. If the user data for the given id
* doesn't already exist in the storage, it should be created.
*
* @param userId unique user id
* @return user data
*/
User getUser(String userId);
/**
* Returns user data given user id. If the user data for the given id
* doesn't already exist in the storage, it should be created. email
* is the email address currently associated with this user. If it
* doesn't match the stored email address (or if the user doesn't exist yet)
* the stored email address will be updated to this one.
*
* @param userId unique user id
* @return user data
*/
User getUser(String userId, String email);
/**
* Returns user data given user email address. If the user data for the given email
* doesn't already exist in the storage, it should be created. email
* is the email address currently associated with this user.
*
* @param user email address
* @return user data
*/
User getUserFromEmail(String email);
/**
* Sets the stored email address for user with id userId
*
*/
void setUserEmail(String userId, String email);
/**
* Sets that the user has accepted the terms of service.
*
* @param userId user id
*/
void setTosAccepted(String userId);
/**
* Sets the user's session id value which is used to ensure only
* one valid session exists for a user
*
* @param userId user id
* @param sessionId the session id (uuid) value
*/
void setUserSessionId(String userId, String sessionId);
/**
* Sets the user's hashed password.
*
* @param userId user id
* @param hashed password
*/
void setUserPassword(String userId, String password);
/**
* Returns a string with the user's settings.
*
* @param userId user id
* @return settings
*/
String loadSettings(String userId);
/**
* Sets the stored name for user with id userId
*
*/
void setUserName(String userId, String name);
/**
* Returns a string with the user's name.
*
* @param userId user id
* @return name
*/
String getUserName(String userId);
/**
* Returns a string with the user's name.
*
* @param userId user id
* @return name
*/
String getUserLink(String userId);
/**
* Sets the stored link for user with id userId
*
*/
void setUserLink(String userId, String link);
/**
* Returns the email notification frequency
*
* @param userId user id
* @return emailFrequency email frequency
*/
int getUserEmailFrequency(String userId);
/**
* Sets the stored email notification frequency for user with id userId
*
*/
void setUserEmailFrequency(String userId, int emailFrequency);
/**
* Stores a string with the user's settings.
*
* @param userId user ID
* @param settings user's settings
*/
void storeSettings(String userId, String settings);
// Project management
/**
* Creates a new project and uploads the files.
*
* <p>
* This is an atomic operation.
*
* @param userId user id
* @param project project information
* @param projectSettings project settings
* @return project id
*/
long createProject(String userId, Project project, String projectSettings);
/**
* Deletes a project and all its files.
*
* @param userId user ID
* @param projectId project ID
*/
void deleteProject(String userId, long projectId);
/**
* Returns an array with the user's projects.
*
* @param userId user ID
* @return list of projects
*/
List<Long> getProjects(String userId);
/**
* sets a projects gallery id when it is published
* @param userId a user Id (the request is made on behalf of this user)*
* @param projectId project ID
* @param galleryId gallery ID
*/
void setProjectGalleryId(final String userId, final long projectId,final long galleryId);
/**
* sets a projects attribution id when it is opened from a gallery project
* @param userId a user Id (the request is made on behalf of this user)*
* @param projectId project ID
* @param attributionId attribution ID
*/
void setProjectAttributionId(final String userId, final long projectId,final long attributionId);
/**
* Returns a string with the project settings.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @return settings
*/
String loadProjectSettings(String userId, long projectId);
/**
* Stores a string with the project settings.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param settings project settings
*/
void storeProjectSettings(String userId, long projectId, String settings);
/**
* Returns the project type.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
*
* @return project type
*/
String getProjectType(String userId, long projectId);
/**
* Returns the ProjectData object complete.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
* @return new UserProject object
*/
UserProject getUserProject(String userId, long projectId);
/**
* Bulk version of getUserProject.
* @param userId a userId
* @param projectIds a List of project ids
* @return new List of UserProject objects
*/
List<UserProject> getUserProjects(String userId, List<Long> projectIds);
/**
* Returns a project name.
*
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
* @return project name
*/
String getProjectName(String userId, long projectId);
/**
* Returns the date the project was last modified.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
*
* @return long milliseconds
*/
long getProjectDateModified(String userId, long projectId);
/**
* Returns the specially formatted list of project history.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
*
* @return String specially formatted history
*/
String getProjectHistory(String userId, long projectId);
// JIS XXX
/**
* Returns the date the project was created.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
*
* @return long milliseconds
*/
long getProjectDateCreated(String userId, long projectId);
/**
* Returns the gallery id or -1 if not published.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project id
*
* @return long milliseconds
*/
// long getGalleryId(String userId, long projectId);
// Non-project-specific file management
/**
* Adds file IDs to the user's list of non-project-specific files.
*
* @param userId a user Id (the request is made on behalf of this user)
* @param fileIds list of file IDs to add to the projects source file list
*/
void addFilesToUser(String userId, String... fileIds);
/**
* Returns a list of non-project-specific files for a user.
*
* @param userId a user Id
* @return list of source file ID
*/
List<String> getUserFiles(String userId);
/**
* Uploads a non-project-specific file.
*
* @param userId user ID
* @param fileId file ID
* @param content file content
* @param encoding encoding of content
*/
void uploadUserFile(String userId, String fileId, String content, String encoding);
/**
* Uploads a non-project-specific file.
*
* @param userId user ID
* @param content file content
* @param fileName file name
*/
void uploadRawUserFile(String userId, String fileName, byte[] content);
/**
* Downloads text user file data.
*
* @param userId a user Id
* @param fileId file ID
* @param encoding encoding of text file
*
* @return text file content
*/
String downloadUserFile(String userId, String fileId, String encoding);
/**
* Downloads raw user file data.
*
* @param userId a user Id
* @param fileName file name
*
* @return file content
*/
byte[] downloadRawUserFile(String userId, String fileName);
/**
* Deletes a user file.
* @param userId a user Id (the request is made on behalf of this user)
* @param fileId file ID
*/
void deleteUserFile(String userId, String fileId);
// File management
/**
* Returns the maximum allowed job size in bytes.
*
* @return int maximum job size in bytes
*/
int getMaxJobSizeBytes();
/**
* Adds file IDs to the project's list of source files, updating the
* modification date of the project if requested. Note that no
* modification date is returned.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param changeModDate update the modification time for the project
* @param fileIds list of file IDs to add to the projects source file list
*/
void addSourceFilesToProject(String userId, long projectId, boolean changeModDate,
String...fileIds);
/**
* Add file IDs to the project's list of output files.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param fileIds list of file IDs to add to the projects output file list
*/
void addOutputFilesToProject(String userId, long projectId, String...fileIds);
/**
* Removes file IDs from the project's list of source files, updating the
* modification date of the project if requested. Note that no
* modification date is returned.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param changeModDate update the modification time for the project
* @param fileIds list of file IDs to add to the projects source file list
*/
void removeSourceFilesFromProject(String userId, long projectId, boolean changeModDate,
String...fileIds);
/**
* Removes file IDs from the project's list of output files.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param fileIds list of file IDs to add to the projects source file list
*/
void removeOutputFilesFromProject(String userId, long projectId, String...fileIds);
/**
* Returns a list of source files for a project.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
*
* @return list of source file ID
*/
List<String> getProjectSourceFiles(String userId, long projectId);
/**
* Returns a list of output files for a project.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
*
* @return list of output file ID
*/
List<String> getProjectOutputFiles(String userId, long projectId);
/**
* Returns the gallery id for a project.
* @param projectId project ID
*
* @return list of output file ID
*/
long getProjectGalleryId(String userId, final long projectId);
/**
* Returns the attribution id for a project-- the app it was copied/remixed from
* @param projectId project ID
*
* @return galleryId
*/
long getProjectAttributionId(final long projectId);
/**
* Uploads a file.
* @param projectId project ID
* @param fileId file ID
* @param userId the user who owns the file
* @param content file content
* @param encoding encoding of content
* @return modification date for project
*/
long uploadFile(long projectId, String fileId, String userId, String content, String encoding)
throws BlocksTruncatedException;
/**
* Uploads a file. -- This version uses "force" to write even a trivial workspace file
* @param projectId project ID
* @param fileId file ID
* @param userId the user who owns the file
* @param content file content
* @param encoding encoding of content
* @return modification date for project
*/
long uploadFileForce(long projectId, String fileId, String userId, String content, String encoding);
/**
* Uploads a file.
* @param projectId project ID
* @param fileId file ID
* @param userId the user who owns the file
* @param force write file even if it is a trivial workspace
* @param content file content
* @return modification date for project
*/
long uploadRawFile(long projectId, String fileId, String userId, boolean force, byte[] content)
throws BlocksTruncatedException;
/**
* Uploads a file. -- forces the save even with trivial workspace
* @param projectId project ID
* @param fileId file ID
* @param userId the user who owns the file
* @param content file content
* @return modification date for project
*/
long uploadRawFileForce(long projectId, String fileId, String userId, byte[] content);
/**
* Deletes a file.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param fileId file ID
* @return modification date for project
*/
long deleteFile(String userId, long projectId, String fileId);
/**
* Downloads text file data.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param fileId file ID
* @param encoding encoding of text file
*
* @return text file content
*/
String downloadFile(String userId, long projectId, String fileId, String encoding);
/**
* Records a "corruption" record so we can analyze if corruption is
* happening.
*
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param message The message from the exception on the client
*/
void recordCorruption(String userId, long projectId, String fileId, String message);
/**
* Downloads raw file data.
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param fileId file ID
*
* @return file content
*/
byte[] downloadRawFile(String userId, long projectId, String fileId);
/**
* Creates a temporary file with the given content and returns
* its file name, which will always begin with __TEMP__
* @param content the files content (bytes)
*
* @return fileName the temporary filename
*/
String uploadTempFile(byte [] content) throws IOException;
/**
* Open an input stream to a temp file.
* Verifies it is a temp file by making sure the filename
* begins with __TEMP__
*
* @param fileName
*
* @return inputstream
*/
InputStream openTempFile(String fileName) throws IOException;
/**
* delete a temporary file.
* Verify that it is a temporary file by making sure its filename
* starts with __TEMP__
*
* @param fileName
*/
void deleteTempFile(String fileName) throws IOException;
// MOTD management
/**
* Returns the most recent motd.
*
* @return motd
*/
Motd getCurrentMotd();
/**
* Exports project files as a zip archive
* @param userId a user Id (the request is made on behalf of this user)
* @param projectId project ID
* @param includeProjectHistory whether or not to include the project history
* @param includeAndroidKeystore whether or not to include the Android keystore
* @param zipName the name of the zip file, if a specific one is desired
* @param fatalError set true to cause missing GCS file to throw exception
*
* @return project with the content as requested by params.
*/
ProjectSourceZip exportProjectSourceZip(String userId, long projectId,
boolean includeProjectHistory,
boolean includeAndroidKeystore,
@Nullable String zipName,
final boolean includeYail,
final boolean includeScreenShots,
final boolean forGallery,
final boolean fatalError) throws IOException;
/**
* Find a user's id given their email address. Note that this query is case
* sensitive!
*
* @param email user's email address
*
* @return the user's id if found
* @throws NoSuchElementException if we can't find a user with that exact
* email address
*/
String findUserByEmail(String email) throws NoSuchElementException;
/**
* Find a phone's IP address given the six character key. Used by the
* RendezvousServlet. This is used only when memcache is unavailable.
*
* @param key the six character key
* @return Ip Address as string or null if not found
*
*/
String findIpAddressByKey(String key);
/**
* Store a phone's IP address indexed by six character key. Used by the
* RendezvousServlet. This is used only when memcache is unavailable.
*
* Note: Nothing currently cleans up these entries, but we have a
* timestamp field which we update so a later process can recognize
* and remove stale entries.
*
* @param key the six character key
* @param ipAddress the IP Address of the phone
*
*/
void storeIpAddressByKey(String key, String ipAddress);
boolean checkWhiteList(String email);
void storeFeedback(final String notes, final String foundIn, final String faultData,
final String comments, final String datestamp, final String email, final String projectId);
Nonce getNoncebyValue(String nonceValue);
void storeNonce(final String nonceValue, final String userId, final long projectId);
// Cleanup expired nonces
void cleanupNonces();
// Check to see if user needs projects upgraded (moved to GCS)
// if so, add task to task queue
void checkUpgrade(String userId);
// Called by the task queue to actually upgrade user's projects
void doUpgrade(String userId);
// Retrieve the current Splash Screen Version
SplashConfig getSplashConfig();
StoredData.PWData createPWData(String email);
StoredData.PWData findPWData(String uid);
void cleanuppwdata();
// Routines for user admin interface
List<AdminUser> searchUsers(String partialEmail);
void storeUser(AdminUser user) throws AdminInterfaceException;
}