#include #include "R_helpers_p.h" #include "R_list_item.h" #include "R_timestamp.h" #include "modb_database.h" #include "modb_ref.h" #include "R_modb_users.h" #include "R_modb_groups.h" SEXP userToR(struct user_t *user, int with_groups) { SEXP r_user; SEXP r_username; SEXP r_email; SEXP r_groups = R_NilValue; SEXP r_attrib_names; SEXP r_class; int n_protect = 0; size_t idx; r_username = PROTECT(Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(r_username, 0, PROTECT(Rf_mkChar(user->username_c))); n_protect += 2; r_email = PROTECT(Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(r_email, 0, PROTECT(Rf_mkChar(user->email_c))); n_protect += 2; r_user = PROTECT(Rf_allocVector(VECSXP, 6 + (with_groups ? 1 : 0))); SET_VECTOR_ELT(r_user, 0, PROTECT(Rf_ScalarInteger((int)user->id))); SET_VECTOR_ELT(r_user, 1, r_username); SET_VECTOR_ELT(r_user, 2, r_email); SET_VECTOR_ELT(r_user, 3, PROTECT(R_Timestamp(user->created_on))); SET_VECTOR_ELT(r_user, 4, PROTECT(R_Timestamp(user->updated_on))); SET_VECTOR_ELT(r_user, 5, PROTECT(R_Timestamp(user->deleted_on))); n_protect += 1 + 4; r_attrib_names = PROTECT(Rf_allocVector(STRSXP, 6 + (with_groups ? 1 : 0))); SET_STRING_ELT(r_attrib_names, 0, PROTECT(Rf_mkChar("id"))); SET_STRING_ELT(r_attrib_names, 1, PROTECT(Rf_mkChar("username"))); SET_STRING_ELT(r_attrib_names, 2, PROTECT(Rf_mkChar("email"))); SET_STRING_ELT(r_attrib_names, 3, PROTECT(Rf_mkChar("created_on"))); SET_STRING_ELT(r_attrib_names, 4, PROTECT(Rf_mkChar("updated_on"))); SET_STRING_ELT(r_attrib_names, 5, PROTECT(Rf_mkChar("deleted_on"))); n_protect += 1 + 6; if (with_groups) { r_groups = PROTECT(Rf_allocVector(VECSXP, (int)user->n_groups)); for (idx = 0; idx < user->n_groups; idx++) { SET_VECTOR_ELT(r_groups, (int)idx, PROTECT(groupToR(*(user->groups + idx), 0))); } SET_VECTOR_ELT(r_user, 6, r_groups); n_protect += 1 + (int)user->n_groups; SET_STRING_ELT(r_attrib_names, 6, PROTECT(Rf_mkChar("groups"))); n_protect++; } Rf_setAttrib(r_user, R_NamesSymbol, r_attrib_names); r_class = PROTECT(Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(r_class, 0, PROTECT(Rf_mkChar("list"))); SET_STRING_ELT(r_class, 1, PROTECT(Rf_mkChar("modb_user"))); Rf_setAttrib(r_user, R_ClassSymbol, r_class); n_protect += 1 + 2; UNPROTECT(n_protect); return r_user; } SEXP rmodb_userId(SEXP r_conn_ref, SEXP r_name_or_email) { stored_conn *sconn; modb_ref modb; const char *search = 0; int is_email = 0; size_t idx = 0; struct user_t *user = 0; SEXP r_user_id; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } if (!modbFindUse(sconn, &modb)) { Rf_error("invalid modb reference\n"); } search = Rf_translateCharUTF8(STRING_ELT(r_name_or_email, 0)); for (idx = 0; idx < strlen(search); idx++) { if (*(search + idx) == '@') { is_email = 1; } } if (!is_email && modbUserByName(sconn, &modb, search, 0, &user) <= 0) { return Rf_ScalarInteger(-1); } if (is_email && modbUserByEmail(sconn, &modb, search, 0, &user) <= 0) { return Rf_ScalarInteger(-1); } r_user_id = PROTECT(Rf_ScalarInteger((int)user->id)); freeUser(&user); UNPROTECT(1); return r_user_id; } SEXP rmodb_users(SEXP r_conn_ref, SEXP r_with_groups, SEXP r_with_deleted) { stored_conn *sconn; modb_ref modb; int with_deleted = 0, with_groups = 0; struct user_t **users = 0; size_t n_users = 0; size_t idx; SEXP r_users; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } if (!modbFindUse(sconn, &modb)) { Rf_error("invalid modb reference\n"); } with_deleted = Rf_asLogical(r_with_deleted); with_groups = Rf_asLogical(r_with_groups); if (modbUserList(sconn, &modb, with_deleted, with_groups, &users, &n_users) <= 0) { return R_NilValue; } r_users = PROTECT(Rf_allocVector(VECSXP, (int)n_users)); for (idx = 0; idx < n_users; idx++) { SET_VECTOR_ELT(r_users, (int)idx, PROTECT(userToR(*(users + idx), with_groups))); } freeUsers(&users, n_users); UNPROTECT((int)(1 + n_users)); return r_users; } SEXP rmodb_user(SEXP r_conn_ref, SEXP r_id, SEXP r_with_groups) { stored_conn *sconn; modb_ref modb; unsigned int user_id = 0; int with_groups = 0; struct user_t *user = 0; SEXP r_user; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } if (!modbFindUse(sconn, &modb)) { Rf_error("invalid modb reference\n"); } user_id = (unsigned int)Rf_asInteger(r_id); with_groups = Rf_asLogical(r_with_groups); if (modbUserById(sconn, &modb, user_id, with_groups, &user) <= 0) { return R_NilValue; } r_user = PROTECT(userToR(user, with_groups)); freeUser(&user); UNPROTECT(1); return r_user; } SEXP rmodb_createUser(SEXP r_conn_ref, SEXP r_id, SEXP r_name, SEXP r_email) { stored_conn *sconn; modb_ref modb; struct user_t user; int64_t res; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } if (!modbFindUse(sconn, &modb)) { Rf_error("invalid modb reference\n"); } bzero(&user, sizeof(struct user_t)); user.id = (unsigned int)Rf_asInteger(r_id); user.username_c = Rf_translateCharUTF8(STRING_ELT(r_name, 0)); user.email_c = Rf_translateCharUTF8(STRING_ELT(r_email, 0)); res = modbUserCreate(sconn, &modb, &user); return Rf_ScalarReal((double)res); } SEXP rmodb_deleteUser(SEXP r_conn_ref, SEXP r_id) { stored_conn *sconn; modb_ref modb; unsigned int user_id = 0; if ((sconn = getConnectionByRef(r_conn_ref)) == 0) { Rf_error("invalid connection reference\n"); } if (!modbFindUse(sconn, &modb)) { Rf_error("invalid modb reference\n"); } user_id = (unsigned int)Rf_asInteger(r_id); return Rf_ScalarLogical(modbUserDelete(sconn, &modb, user_id)); }