package org.commcare.models.database.user; import android.content.Context; import net.sqlcipher.database.SQLiteDatabase; import org.commcare.CommCareApp; import org.commcare.CommCareApplication; import org.commcare.google.services.analytics.GoogleAnalyticsFields; import org.commcare.google.services.analytics.GoogleAnalyticsUtils; import org.commcare.models.database.ConcreteAndroidDbHelper; import org.commcare.models.database.SqlStorage; import org.commcare.android.database.app.models.UserKeyRecord; import org.commcare.core.encryption.CryptUtil; import org.commcare.models.encryption.ByteEncrypter; import org.javarosa.core.model.User; import org.javarosa.core.util.PropertyUtils; import java.util.Date; import javax.crypto.SecretKey; /** * Demo KeyRecord and User creation * * @author ctsims */ public class DemoUserBuilder { public static final String DEMO_USERNAME = "demo_user"; public static final String DEMO_PASSWORD = "demo_user"; private final Context context; private final SqlStorage<UserKeyRecord> keyRecordDB; private final String username; private final String password; private final String userType; private String passwordHash; private byte[] randomKey; private DemoUserBuilder(Context context, CommCareApp ccApp, String username, String password, boolean isDemo) { this.context = context; this.keyRecordDB = ccApp.getStorage(UserKeyRecord.class); this.username = username; this.password = password; if (isDemo) { userType = User.TYPE_DEMO; } else { userType = User.STANDARD; } } /** * Create demo UserKeyRecord and User and write it to the database */ public static synchronized void build(Context context, CommCareApp ccApp) { (new DemoUserBuilder(context, ccApp, DEMO_USERNAME, DEMO_PASSWORD, true)).createAndWriteKeyRecordAndUser(); GoogleAnalyticsUtils.reportFeatureUsage(GoogleAnalyticsFields.ACTION_LOGIN_AS_DEMO_USER); } /** * Create a test UserKeyRecord and User for testing purposes, writing them to the database. */ public static synchronized void buildTestUser(Context context, CommCareApp ccApp, String username, String password) { (new DemoUserBuilder(context, ccApp, username, password, false)).createAndWriteKeyRecordAndUser(); } private void createAndWriteKeyRecordAndUser() { int userCount = keyRecordDB.getIDsForValue(UserKeyRecord.META_USERNAME, username).size(); if (userCount == 0) { SecretKey secretKey = CryptUtil.generateSemiRandomKey(); if (secretKey == null) { throw new RuntimeException("Error setting up user's encrypted storage"); } randomKey = secretKey.getEncoded(); passwordHash = UserKeyRecord.generatePwdHash(password); UserKeyRecord keyRecord = writeNewKeyRecord(); writeNewUser(keyRecord); } } private UserKeyRecord writeNewKeyRecord() { byte[] encryptedKey = ByteEncrypter.wrapByteArrayWithString(randomKey, password); UserKeyRecord keyRecord = new UserKeyRecord(username, passwordHash, encryptedKey, new Date(0), new Date(Long.MAX_VALUE - 1), PropertyUtils.genUUID().replace("-", "")); keyRecordDB.write(keyRecord); return keyRecord; } private void writeNewUser(UserKeyRecord keyRecord) { SQLiteDatabase userDatabase = null; try { userDatabase = new DatabaseUserOpenHelper(CommCareApplication.instance(), keyRecord.getUuid()).getWritableDatabase(UserSandboxUtils.getSqlCipherEncodedKey(randomKey)); User user = new User(username, passwordHash, username, userType); SqlStorage<User> userStorage = new SqlStorage<>(User.STORAGE_KEY, User.class, new ConcreteAndroidDbHelper(context, userDatabase)); userStorage.write(user); } finally { if (userDatabase != null) { userDatabase.close(); } } } }