308 lines
9.2 KiB
C++
308 lines
9.2 KiB
C++
#include "userdb.h"
|
|
|
|
#include <bson/bson.h>
|
|
#include <bson/memory.h>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <mongoc/mongoc.h>
|
|
#include <stdio.h>
|
|
|
|
static mongoc_client_t* client = NULL;
|
|
static mongoc_database_t* db = NULL;
|
|
static mongoc_collection_t* collection = NULL;
|
|
|
|
// Initialize MongoDB client
|
|
int userdb_init(const char* host, int port) {
|
|
|
|
const char* target = "mongodb://mongoadmin:secret@127.0.0.1:27017";
|
|
mongoc_uri_t* uri = mongoc_uri_new(target);
|
|
bson_error_t error;
|
|
|
|
// Initialize the C Driver
|
|
mongoc_init();
|
|
|
|
// Create a new client and connect to the server
|
|
mongoc_client_t *client = mongoc_client_new_from_uri(uri);
|
|
if (!client) {
|
|
fprintf(stderr, "Failed to create MongoDB client\n");
|
|
return -1;
|
|
}
|
|
db = mongoc_client_get_database(client, "userdb");
|
|
if (!db) {
|
|
fprintf(stderr, "Failed to get database\n");
|
|
mongoc_client_destroy(client);
|
|
return -1;
|
|
}
|
|
|
|
bson_t *ping = BCON_NEW("ping", BCON_INT32(1));
|
|
bson_t reply = BSON_INITIALIZER;
|
|
bson_t* options;
|
|
|
|
collection = mongoc_database_create_collection(db, "users", NULL, &error);
|
|
if(!collection) {
|
|
|
|
if(error.code == 43) { // if collection exists
|
|
collection = mongoc_database_get_collection(db, "users");
|
|
if (!collection) {
|
|
fprintf(stderr, "Failed to get collection\n");
|
|
mongoc_client_destroy(client);
|
|
return -1;
|
|
}
|
|
} else {
|
|
printf("bad thing has happed %d, %s\n", error.code, error.message);
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Create user
|
|
//int userdb_create_user(const char* username, const char* email, const char* password_hash, const char** user_tags, int size_of_user_tags) {
|
|
int userdb_create_user(UserCreate user) {
|
|
bson_t* doc = NULL;
|
|
bson_error_t error;
|
|
int ret = 0;
|
|
bson_t* array = bson_new();
|
|
|
|
if(!array) {
|
|
printf("Failed to create BSON document\n");
|
|
ret = -2;
|
|
goto cleanup;
|
|
}
|
|
|
|
for(int i = 0; i < user.size_of_user_tags; i++) {
|
|
char id[32] = {0};
|
|
snprintf(id,32,"%d", i);
|
|
bson_append_utf8(array, id, -1, user.user_tags[i], -1);
|
|
}
|
|
|
|
|
|
doc = bson_new();
|
|
|
|
|
|
if (!doc) {
|
|
printf("Failed to create BSON document\n");
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// This is the old way of doing things --V
|
|
//doc = BCON_NEW(
|
|
// "username", BCON_UTF8(username),
|
|
// "email", BCON_UTF8(email),
|
|
// "password_hash", BCON_UTF8(password_hash),
|
|
// "session_id", BCON_UTF8(""),
|
|
// "active", BCON_INT32(1)
|
|
//);
|
|
//
|
|
|
|
|
|
|
|
bson_append_utf8(doc, "username", -1, user.username, -1);
|
|
bson_append_utf8(doc, "email", -1, user.email, -1);
|
|
bson_append_utf8(doc, "password_hash", -1, user.password_hash, -1);
|
|
bson_append_utf8(doc, "session_id", -1, user.session_id, strlen(user.session_id));
|
|
bson_append_utf8(doc, "last_page", -1, "/", -1);
|
|
|
|
bson_append_array(doc,"tags", -1, array);
|
|
|
|
if (!mongoc_collection_insert_one(collection, doc, NULL, NULL, &error)) {
|
|
fprintf(stderr, "Insert failed: %s\n", error.message);
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if (doc) {
|
|
bson_destroy(doc);
|
|
}
|
|
if(array) {
|
|
bson_destroy(array);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Find user by username
|
|
Userdb* userdb_find_user_by_username(const char* username) {
|
|
Userdb* user = (Userdb*)malloc(sizeof(Userdb));
|
|
if (!user) {
|
|
return NULL;
|
|
}
|
|
|
|
bson_t* query = BCON_NEW("username", BCON_UTF8(username));
|
|
bson_error_t error;
|
|
mongoc_cursor_t* cursor = mongoc_collection_find_with_opts(collection, query, NULL, NULL);
|
|
if (!cursor) {
|
|
fprintf(stderr, "Find failed\n");
|
|
free(user);
|
|
return NULL;
|
|
}
|
|
|
|
bson_iter_t iter;
|
|
const bson_t* doc;
|
|
|
|
if(mongoc_cursor_next(cursor, &doc)) {
|
|
bson_iter_init(&iter, doc);
|
|
|
|
|
|
|
|
strncpy(user->username, username, USERDB_USERNAME_MAX_SIZE);
|
|
|
|
if(bson_iter_find(&iter, "email")) {
|
|
const char* email = bson_iter_utf8(&iter, NULL);
|
|
if(email && strlen(email) < USERDB_EMAIL_MAX_SIZE) {
|
|
strcpy(user->email, email);
|
|
}
|
|
user->email[USERDB_EMAIL_MAX_SIZE - 1] = '\0';
|
|
}
|
|
if(bson_iter_find(&iter, "password_hash")) {
|
|
const char* password_hash = bson_iter_utf8(&iter, NULL);
|
|
if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) {
|
|
strcpy(user->password_hash, password_hash);
|
|
}
|
|
user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0';
|
|
}
|
|
if(bson_iter_find(&iter, "user_group")) {
|
|
const char* user_group = bson_iter_utf8(&iter, NULL);
|
|
if(user_group && strlen(user_group) < USERDB_USER_GROUP_MAX_SIZE) {
|
|
strcpy(user->user_group, user_group);
|
|
}
|
|
user->user_group[USERDB_USER_GROUP_MAX_SIZE - 1] = '\0';
|
|
}
|
|
if(bson_iter_find(&iter, "user_freads")) {
|
|
const char* password_hash = bson_iter_utf8(&iter, NULL);
|
|
if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) {
|
|
strcpy(user->password_hash, password_hash);
|
|
}
|
|
user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0';
|
|
}
|
|
if(bson_iter_find(&iter, "user_freads")) {
|
|
const char* password_hash = bson_iter_utf8(&iter, NULL);
|
|
if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) {
|
|
strcpy(user->password_hash, password_hash);
|
|
}
|
|
user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0';
|
|
}
|
|
|
|
if(bson_iter_find(&iter, "level")) {
|
|
user->level = bson_iter_int32(&iter);
|
|
}
|
|
if(bson_iter_find(&iter, "current_xp")) {
|
|
user->current_xp = bson_iter_int32(&iter);
|
|
}
|
|
if(bson_iter_find(&iter, "credits")) {
|
|
user->credits = bson_iter_int32(&iter);
|
|
}
|
|
if(bson_iter_find(&iter, "runs")) {
|
|
user->runs = bson_iter_int32(&iter);
|
|
}
|
|
if(bson_iter_find(&iter, "active")) {
|
|
user->active = bson_iter_int32(&iter);
|
|
}
|
|
}
|
|
|
|
bson_destroy(query);
|
|
return user;
|
|
}
|
|
|
|
// Find user by username
|
|
User* userdb_find_user_by_username(const char* username) {
|
|
User* user = (User*)malloc(sizeof(User));
|
|
if (!user) {
|
|
return NULL;
|
|
}
|
|
|
|
bson_t* query = BCON_NEW("username", BCON_UTF8(username));
|
|
bson_error_t error;
|
|
mongoc_cursor_t* cursor = mongoc_collection_find_with_opts(collection, query, NULL, NULL);
|
|
|
|
if (!cursor) {
|
|
fprintf(stderr, "Find failed\n");
|
|
bson_destroy(query);
|
|
free(user);
|
|
return NULL;
|
|
}
|
|
|
|
bson_iter_t iter;
|
|
const bson_t* doc;
|
|
|
|
if(mongoc_cursor_next(cursor, &doc)) {
|
|
if(bson_iter_init(&iter, doc)) {
|
|
|
|
char* res = bson_as_canonical_extended_json(doc, NULL);
|
|
printf("resolt :%s\n", res);
|
|
bson_free(res);
|
|
|
|
if(bson_iter_find(&iter, "email")) {
|
|
const char* email = bson_iter_utf8(&iter, NULL);
|
|
if(email && strlen(email) < USERDB_EMAIL_MAX_SIZE) {
|
|
strcpy(user->email, email);
|
|
}
|
|
user->email[USERDB_EMAIL_MAX_SIZE - 1] = '\0';
|
|
}
|
|
|
|
if(bson_iter_find(&iter, "password_hash")) {
|
|
const char* password_hash = bson_iter_utf8(&iter, NULL);
|
|
if(password_hash && strlen(password_hash) < USERDB_PASSWORD_HASH_MAX_SIZE) {
|
|
strcpy(user->password_hash, password_hash);
|
|
}
|
|
user->password_hash[USERDB_PASSWORD_HASH_MAX_SIZE - 1] = '\0';
|
|
}
|
|
|
|
if(bson_iter_find(&iter, "session_id")) {
|
|
const char* username = bson_iter_utf8(&iter, NULL);
|
|
if(username && strlen(username) < USERDB_USERNAME_MAX_SIZE) {
|
|
strcpy(user->username, username);
|
|
}
|
|
user->username[USERDB_USERNAME_MAX_SIZE - 1] = '\0';
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
bson_destroy(query);
|
|
mongoc_cursor_destroy(cursor);
|
|
return user;
|
|
}
|
|
|
|
// Update user status
|
|
int userdb_update_user_status(const char* username, int active) {
|
|
const bson_t* filter = BCON_NEW("username", BCON_UTF8(username));
|
|
const bson_t* update = BCON_NEW("$set", BCON_DOCUMENT(BCON_NEW("active", BCON_INT32(active))));
|
|
bson_error_t error;
|
|
|
|
if (mongoc_collection_insert_one(collection, filter, update, NULL, &error) == 0) {
|
|
fprintf(stderr, "Update failed: %s\n", error.message);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Delete user
|
|
int userdb_delete_user(const char* username) {
|
|
const bson_t* filter = BCON_NEW("username", BCON_UTF8(username));
|
|
bson_error_t error;
|
|
|
|
if (mongoc_collection_delete_one(collection, filter,NULL, NULL, &error) == 0) {
|
|
fprintf(stderr, "Delete failed: %s\n", error.message);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Cleanup
|
|
void userdb_cleanup() {
|
|
if (collection) {
|
|
mongoc_collection_destroy(collection);
|
|
}
|
|
if (db) {
|
|
mongoc_database_destroy(db);
|
|
}
|
|
if (client) {
|
|
mongoc_client_destroy(client);
|
|
}
|
|
mongoc_cleanup();
|
|
}
|