// -*- 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.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cached; import com.googlecode.objectify.annotation.Parent; import com.googlecode.objectify.annotation.Indexed; import com.googlecode.objectify.annotation.Unindexed; import java.io.Serializable; import java.util.Date; import javax.persistence.Id; /** * Classes for the data objects that are stored in the Objectify database. * * TODO(user): for now I just defined a bunch of classes (parallel * to the ones in the old ode.proto). It might be * worth considering whether to make these classes extend DAOBasic (does it buy * us anything) and whether to add any methods for manipulating the objects. * * TODO(user): consider separating these out into individual class * files - more Java-y? * * @author sharon@google.com (Sharon Perl) * */ public class StoredData { // The UserData class is an entity root, and the parent of UserFileData // and UserProjectData @Unindexed @Cached public static final class UserData { // The Google Account userid @Id public String id; @Indexed public String email; @Indexed public String emaillower; // User settings public String settings; // Has user accepted terms of service? boolean tosAccepted; boolean isAdmin; // Internal flag for local login administrators @Indexed public Date visited; // Used to figure out if a user is active. Timestamp when settings are stored. public String name; public String link; public int emailFrequency; public int type; String sessionid; // uuid of active session String password; // Hashed (PBKDF2 hashing) password // Path to template project passed as GET parameter String templatePath; boolean upgradedGCS; } // Project properties // The ProjectData class is an entity root, and the parent of FileData @Cached @Unindexed static final class ProjectData { // Auto-generated unique project id @Id Long id; // Verbose project name String name; //introduction link String link; // Project type. Currently Simple and YoungAndroid // TODO(user): convert to enum String type; // Global project settings String settings; // Date project created // TODO(): Make required long dateCreated; // Date project last modified // TODO(): Make required long dateModified; // The specially formatted project history String history; long galleryId; // this is the galleryId of this project (if published) long attributionId; // if this project was initiated from the gallery, this is // the id of the gallery app that was copied for remix } // Project properties specific to the user @Unindexed static final class UserProjectData { enum StateEnum { CLOSED, OPEN, DELETED } // The project id @Id long projectId; // The user (parent's) key @Parent Key<UserData> userKey; // State of the project relative to user // TODO(user): is this ever used? StateEnum state; // User specific project settings // TODO(user): is this ever used? String settings; } // Non-project-specific files (tied to user) @Unindexed static final class UserFileData { // The file name @Id String fileName; // The user (parent's) key @Parent Key<UserData> userKey; // File content, these are raw bytes. Note that Objectify automatically // converts byte[] to Blob. byte[] content; // File settings // TODO(user): is this ever used? String settings; } // Project files // Note: FileData has to be Serializable so we can put it into // memcache. @Cached @Unindexed static final class FileData implements Serializable { // The role that file play: source code, build target or temporary file enum RoleEnum { SOURCE, TARGET, TEMPORARY } // The file name @Id String fileName; // Key of the project (parent) to which this file belongs @Parent Key<ProjectData> projectKey; // File role RoleEnum role; // File content, these are raw bytes. Note that Objectify automatically // converts byte[] to an App Engine Datastore Blob (which is not the same thing as a Blobstore // Blob). Consequently, if isBlob is true, the content field should be ignored and the data // should be retrieved from Blobstore. byte[] content; // Is this file stored in Blobstore. If it is, the blobstorePath will contain the path to use // to retrieve the data from Blobstore. boolean isBlob; // The Blobstore path to use to get the data from Blobstore String blobstorePath; // The Blobstore key. This is filled in by a MapReduce job run outside of App Inventor String blobKey; // Is this file stored in the Google Cloud Store (GCS). If it is the gcsName will contain the // GCS file name (sans bucket). Boolean isGCS = false; // The GCS filename, sans bucket name String gcsName; // File settings String settings; // DateTime of last backup only used if GCS is enabled long lastBackup; String userId; // The userId which owns this file // if null or the empty string, we haven't initialized // it yet } // MOTD data. @Unindexed static final class MotdData { // Unique Id - for now we expect there to be only 1 MotdData object. @Id Long id; // Caption for the MOTD String caption; // More MOTD detail, if any String content; } // Rendezvous Data -- Only used when memcache is unavailable @Unindexed static final class RendezvousData { @Id Long id; // Six character key entered by user (or scanned). @Indexed public String key; // Ip Address of phone public String ipAddress; public Date used; // Used during (manual) cleanup to determine if this entry can be pruned } @Unindexed static final class WhiteListData { @Id Long id; @Indexed public String emailLower; } @Unindexed static final class FeedbackData { @Id Long id; public String notes; public String foundIn; public String faultData; public String comments; public String datestamp; public String email; public String projectId; } // NonceData -- A unique (and obscure) nonce is used to map between // the nonce string and a userId and projectId. This is used to provide // for unauthenticated download of an APK file. Nonces are timestamped // both to provide a way to clean them up and to expire the APK downloads. @Unindexed static final class NonceData { @Id Long id; @Indexed public String nonce; public String userId; public long projectId; @Indexed public Date timestamp; } @Unindexed static final class CorruptionRecord { @Id Long id; @Indexed public Date timestamp; public String userId; public long projectId; public String fileId; public String message; } @Cached(expirationSeconds=60) @Unindexed static final class SplashData { @Id Long id; public int version; public String content; public int height; public int width; } // Data Structure to keep track of url's emailed out for password // setting and reseting. The Id (which is a UUID) is part of the URL // that is mailed out. @Unindexed public static final class PWData { @Id public String id; // "Secret" URL part @Indexed public Date timestamp; // So we know when to expire this objects public String email; // Email of account in question } }