int SLNSessionCreateUserInternal(SLNSessionRef const session, DB_txn *const txn, strarg_t const username, strarg_t const password, SLNMode const mode_unsafe) { if(!session) return DB_EINVAL; if(!txn) return DB_EINVAL; if(!username) return DB_EINVAL; if(!password) return DB_EINVAL; size_t const ulen = strlen(username); size_t const plen = strlen(password); if(ulen < USER_MIN || ulen > USER_MAX) return DB_EINVAL; if(plen < PASS_MIN || plen > PASS_MAX) return DB_EINVAL; SLNMode const mode = mode_unsafe & session->mode; if(!mode) return DB_EINVAL; uint64_t const parent = session->userID; uint64_t const time = uv_now(async_loop); // TODO: Appropriate timestamp? uint64_t const userID = db_next_id(SLNUserByID, txn); if(!userID) return DB_EACCES; str_t *passhash = pass_hash(password); if(!passhash) return DB_ENOMEM; DB_val username_key[1], userID_val[1]; SLNUserIDByNameKeyPack(username_key, txn, username); SLNUserIDByNameValPack(userID_val, txn, userID); int rc = db_put(txn, username_key, userID_val, DB_NOOVERWRITE); if(rc < 0) return rc; DB_val userID_key[1], user_val[1]; SLNUserByIDKeyPack(userID_key, txn, userID); SLNUserByIDValPack(user_val, txn, username, passhash, NULL, mode, parent, time); rc = db_put(txn, userID_key, user_val, DB_NOOVERWRITE); if(rc < 0) return rc; return 0; }
int SLNSessionCreateSession(SLNSessionRef const session, SLNSessionRef *const out) { assert(out); if(!session) return DB_EACCES; SLNSessionCacheRef const cache = session->cache; uint64_t const userID = session->userID; SLNMode const mode = session->mode; strarg_t const username = session->username; DB_env *db = NULL; DB_txn *txn = NULL; SLNSessionRef alt = NULL; byte_t key_raw[SESSION_KEY_LEN]; int rc = async_random(key_raw, sizeof(key_raw)); if(rc < 0) goto cleanup; byte_t key_enc[SHA256_DIGEST_LENGTH]; SHA256(key_raw, sizeof(key_raw), key_enc); str_t key_str[SESSION_KEY_HEX+1]; tohex(key_str, key_enc, SESSION_KEY_LEN); key_str[SESSION_KEY_HEX] = '\0'; rc = SLNSessionDBOpen(session, SLN_RDWR, &db); // TODO: Custom permission? if(rc < 0) goto cleanup; rc = db_txn_begin(db, NULL, DB_RDWR, &txn); if(rc < 0) goto cleanup; uint64_t const sessionID = db_next_id(SLNSessionByID, txn); DB_val key[1], val[1]; SLNSessionByIDKeyPack(key, txn, sessionID); SLNSessionByIDValPack(val, txn, userID, key_str); rc = db_put(txn, key, val, DB_NOOVERWRITE_FAST); if(rc < 0) goto cleanup; rc = db_txn_commit(txn); txn = NULL; SLNSessionDBClose(session, &db); if(rc < 0) goto cleanup; rc = SLNSessionCreateInternal(cache, sessionID, key_raw, key_enc, userID, mode, username, &alt); if(rc < 0) goto cleanup; *out = alt; alt = NULL; cleanup: db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); SLNSessionRelease(&alt); return rc; }
int SLNSubmissionStore(SLNSubmissionRef const sub, DB_txn *const txn) { assert(sub); assert(txn); assert(!sub->tmppath); // Session permissions were already checked when the sub was created. int64_t fileID = db_next_id(SLNFileByID, txn); int rc; DB_val dupFileID_val[1]; SLNFileIDByInfoValPack(dupFileID_val, txn, fileID); DB_val fileInfo_key[1]; SLNFileIDByInfoKeyPack(fileInfo_key, txn, sub->internalHash, sub->type); rc = db_put(txn, fileInfo_key, dupFileID_val, DB_NOOVERWRITE); if(rc >= 0) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); DB_val file_val[1]; SLNFileByIDValPack(file_val, txn, sub->internalHash, sub->type, sub->size); rc = db_put(txn, fileID_key, file_val, DB_NOOVERWRITE_FAST); if(rc < 0) return rc; } else if(DB_KEYEXIST == rc) { fileID = db_read_uint64(dupFileID_val); } else return rc; for(size_t i = 0; sub->URIs[i]; ++i) { strarg_t const URI = sub->URIs[i]; DB_val null = { 0, NULL }; DB_val fwd[1]; SLNFileIDAndURIKeyPack(fwd, txn, fileID, URI); rc = db_put(txn, fwd, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; DB_val rev[1]; SLNURIAndFileIDKeyPack(rev, txn, URI, fileID); rc = db_put(txn, rev, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; } rc = SLNSubmissionParseMetaFile(sub, fileID, txn, &sub->metaFileID); if(rc < 0) { alogf("Submission meta-file error: %s\n", sln_strerror(rc)); return rc; } return 0; }
static uint64_t add_metafile(DB_txn *const txn, uint64_t const fileID, strarg_t const targetURI) { uint64_t const metaFileID = fileID; uint64_t const latestMetaFileID = db_next_id(SLNMetaFileByID, txn); if(metaFileID < latestMetaFileID) return 0; // If it's not a new file, then it's not a new meta-file. // Note that ordinary files can't be "promoted" to meta-files later // because that would break the ordering. DB_val null = { 0, NULL }; DB_cursor *cursor = NULL; int rc = db_txn_cursor(txn, &cursor); assert(rc >= 0); DB_val metaFileID_key[1]; SLNMetaFileByIDKeyPack(metaFileID_key, txn, metaFileID); DB_val metaFile_val[1]; SLNMetaFileByIDValPack(metaFile_val, txn, fileID, targetURI); rc = db_put(txn, metaFileID_key, metaFile_val, DB_NOOVERWRITE_FAST); assert(rc >= 0); DB_range alts[1]; SLNTargetURIAndMetaFileIDRange1(alts, txn, targetURI); rc = db_cursor_firstr(cursor, alts, NULL, NULL, +1); assert(rc >= 0 || DB_NOTFOUND == rc); if(DB_NOTFOUND == rc) { DB_val unique[1]; SLNFirstUniqueMetaFileIDKeyPack(unique, txn, metaFileID); rc = db_put(txn, unique, &null, DB_NOOVERWRITE_FAST); assert(rc >= 0); } DB_val targetURI_key[1]; SLNTargetURIAndMetaFileIDKeyPack(targetURI_key, txn, targetURI, metaFileID); rc = db_put(txn, targetURI_key, &null, DB_NOOVERWRITE_FAST); assert(rc >= 0); return metaFileID; }