Files
rmodb/src/R_modb_users.c
2020-10-15 14:47:19 +01:00

210 lines
5.8 KiB
C

#include <string.h>
#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));
}