DB integration: initial support. user login by DB.

This commit is contained in:
2025-10-23 15:18:48 +03:00
parent ae2a506f0e
commit 24c4e75943
9 changed files with 196 additions and 78 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
CFLAGS := -ggdb -Wall -pedantic CFLAGS := -ggdb -Wall -pedantic -lpq
SRC_DIR := src SRC_DIR := src
OBJ_DIR := src/obj OBJ_DIR := src/obj
+129
View File
@@ -0,0 +1,129 @@
#include "db.h"
#include <libpq-fe.h>
#include <string.h>
#define UNUSED(x) (void)(x)
#define Q_LEN 128
static PGconn *conn = NULL;
static PGresult *res = NULL;
// #define USR_NOT_FOUND "User with such credentials is not found!"
static void clearRes() {
PQclear(res);
res = NULL;
}
static int terminate(int code) {
if (code != 0)
fprintf(stderr, "%s\n", PQerrorMessage(conn));
if (res != NULL)
PQclear(res);
if (conn != NULL)
PQfinish(conn);
return code;
}
static int exit_query(int code) {
if (code != 0)
fprintf(stderr, "%s\n", PQerrorMessage(conn));
if (res != NULL)
PQclear(res);
return code;
}
static void processNotice(void *arg, const char *message) {
UNUSED(arg);
UNUSED(message);
// do nothing
}
int init_connection() {
// TODO: get from external configs
conn = PQconnectdb("user=postgres password=dobro host=127.0.0.1 dbname=bbs");
if (PQstatus(conn) != CONNECTION_OK)
return terminate(1);
int server_ver = PQserverVersion(conn);
char *user = PQuser(conn);
char *db_name = PQdb(conn);
printf("Connection established! server version: %d, user: %s, db: %s\n", server_ver,
user, db_name);
return exit_query(0);
}
int db_user_auth(i_auth_t *credentials, o_auth_t *response) {
char query[Q_LEN];
response->is_logged = 0;
sprintf(query,
"SELECT username, password, privileges "
"FROM users "
"WHERE username= '%s'",
credentials->name);
res = PQexec(conn, query);
if (PQresultStatus(res) != PGRES_TUPLES_OK && !PQntuples(res))
return exit_query(1);
const char *pass = PQgetvalue(res, 0, 1);
if (!strcmp(pass, credentials->pass)) {
response->is_logged = 1;
response->privileges = PQgetvalue(res, 0, 2)[0];
return exit_query(0);
}
return exit_query(2);
}
/*s
int f_main() {
int libpq_ver = PQlibVersion();
printf("Version of libpq: %d\n", libpq_ver);
conn = PQconnectdb("user=postgres password=dobro host=127.0.0.1 dbname=bbs");
if (PQstatus(conn) != CONNECTION_OK)
terminate(1);
PQsetNoticeProcessor(conn, processNotice, NULL);
int server_ver = PQserverVersion(conn);
char *user = PQuser(conn);
char *db_name = PQdb(conn);
printf("Server version: %d\n", server_ver);
printf("User: %s\n", user);
printf("Database name: %s\n", db_name);
res = PQexec(conn, "SELECT id, username, privileges, email "
"FROM users");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
terminate(1);
int nrows = PQntuples(res);
for (int i = 0; i < nrows; i++) {
char *id = PQgetvalue(res, i, 0);
char *name = PQgetvalue(res, i, 1);
char *privileges = PQgetvalue(res, i, 2);
char *email = PQgetvalue(res, i, 3);
printf("Id: %s, Name: %s, Privileges: %d, Email: %s, \n", id, name,
privileges[0], email);
}
printf("Total: %d rows\n", nrows);
clearRes();
terminate(0);
return 0;
}
*/
+12
View File
@@ -0,0 +1,12 @@
typedef struct {
char *name;
char *pass;
} i_auth_t;
typedef struct {
char privileges;
int is_logged;
} o_auth_t;
int init_connection();
int db_user_auth(i_auth_t *credentials, o_auth_t *response);
+8
View File
@@ -0,0 +1,8 @@
client.o: src/client.c src/client.h src/main.h src/file_p.h src/session.h
db.o: src/db.c src/db.h
file_p.o: src/file_p.c src/file_p.h src/main.h src/session.h
main.o: src/main.c src/main.h src/file_p.h src/server.h src/db.h
server.o: src/server.c src/main.h src/session.h src/user.h
session.o: src/session.c src/session.h src/main.h src/client.h \
src/file_p.h src/user.h
user.o: src/user.c src/main.h src/session.h src/db.h
+2
View File
@@ -1,6 +1,7 @@
#include "main.h" #include "main.h"
#include "file_p.h" #include "file_p.h"
#include "server.h" #include "server.h"
#include "db.h"
/* *** MAIN *** */ /* *** MAIN *** */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@@ -9,6 +10,7 @@ int main(int argc, char *argv[]) {
server_data.welcome_message = get_welcome_mes(); server_data.welcome_message = get_welcome_mes();
server_data.fl_start = NULL; server_data.fl_start = NULL;
server_data.fl_current = NULL; server_data.fl_current = NULL;
init_connection();
get_files_descriptions(&server_data); get_files_descriptions(&server_data);
server_data.ls = start_server(); server_data.ls = start_server();
server_main_loop(&server_data); server_main_loop(&server_data);
+3
View File
@@ -18,13 +18,16 @@ enum sess_states {
OP_EDIT_USER, OP_EDIT_USER,
OP_LOGIN_USR, OP_LOGIN_USR,
OP_LOGIN_PSS, OP_LOGIN_PSS,
OP_LOGIN_ANON,
OP_WAIT, OP_WAIT,
OP_UPLOAD, OP_UPLOAD,
OP_UPLOAD_DESCRIPTION, OP_UPLOAD_DESCRIPTION,
OP_REGISTER,
ERR, ERR,
FIN FIN
}; };
enum user_privileges { enum user_privileges {
ADD_FILE = 01, ADD_FILE = 01,
EDIT_FILES = 02, EDIT_FILES = 02,
+2 -25
View File
@@ -128,38 +128,15 @@ int query_extract_from_buf(session *sess, char **output_line) {
void perform_session_action(session *sess, char *line, server_data_t *s_d) { void perform_session_action(session *sess, char *line, server_data_t *s_d) {
int state = sess->state; int state = sess->state;
char tmp_buf[256];
int priv; int priv;
int tmp_buf_pos;
int res; int res;
/* while (sess->buf_used) { */ /* while (sess->buf_used) { */
switch (state) { switch (state) {
case OP_LOGIN_USR: case OP_LOGIN_USR:
res = find_user(line); process_user_name(line, sess);
if (res == -2) {
sess->state = ERR;
sess->reason = EXIT;
session_send_string(sess, "Bye!");
break;
}
sess->userpos = res;
sess->state = OP_LOGIN_PSS;
session_send_string(sess, "password> ");
break; break;
case OP_LOGIN_PSS: case OP_LOGIN_PSS:
if (sess->userpos == -1) { login(sess, line);
sess->state = ERR;
sess->reason = LOGIN;
} else {
if (login(sess, line)) {
sess->state = OP_WAIT;
sprintf(tmp_buf, "Welcome, %s\n", sess->uname);
session_send_string(sess, tmp_buf);
} else {
sess->state = ERR;
sess->reason = LOGIN;
}
}
break; break;
case OP_WAIT: case OP_WAIT:
process_client_command(line, sess, s_d); process_client_command(line, sess, s_d);
+38 -51
View File
@@ -3,68 +3,55 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "db.h"
long int find_user(char *uname) { int process_user_name(char *uname, session *sess) {
FILE *fptr = fopen(FILE_USER_LIST_NAME, "r");
if (fptr == NULL) {
perror(FILE_USER_LIST_NAME);
exit(9);
}
char *line = NULL;
size_t bsize = WSIZE;
char b_uname[32];
long int cur_pos = 0;
int lsize = 0;
if (!strncmp(uname, "exit", sizeof "exit")) { if (!strncmp(uname, "exit", sizeof "exit")) {
return -2; sess->state = ERR;
sess->reason = EXIT;
session_send_string(sess, "Bye!");
return 1;
} }
while (getline(&line, &bsize, fptr)) { if (!strncmp(uname, "register", sizeof "register")) {
if (line[0] == '\b') sess->state = OP_REGISTER;
break; session_send_string(sess, "Your username > ");
sscanf(line, "%s", b_uname); return 2;
if (!strcmp(uname, b_uname)) {
line = NULL;
fclose(fptr);
return cur_pos;
} else {
cur_pos += lsize;
line = NULL;
}
} }
fclose(fptr); if (!strncmp(uname, "anon", sizeof "anon")) {
return -1; sess->state = OP_LOGIN_ANON;
session_send_string(sess, "Welcome, Anonymous!");
return 3;
}
sess->uname = malloc(strlen(uname) + 1);
strcpy(sess->uname, uname);
sess->state = OP_LOGIN_PSS;
session_send_string(sess, "password> ");
return 0;
} }
/* returns 1 if success */ /* returns 1 if success */
int login(session *sess, char *pass) { int login(session *sess, char *pass) {
FILE *fptr = fopen(FILE_USER_LIST_NAME, "r"); char tmp_string[256];
fseek(fptr, sess->userpos, SEEK_SET); i_auth_t cred;
int res = 0; o_auth_t response;
cred.name = sess->uname;
char *line = NULL; cred.pass = pass;
size_t lsize = WSIZE; db_user_auth(&cred, &response);
char *pass_tok, *name_tok, *priv_tok; if (response.is_logged) {
sess->state = OP_WAIT;
getline(&line, &lsize, fptr); sess->privileges = (char)atoi(&response.privileges);
name_tok = strtok(line, " "); sprintf(tmp_string, "Welcome, %s\n", sess->uname);
pass_tok = strtok(NULL, " "); session_send_string(sess, tmp_string);
return 0;
if (!strcmp(pass_tok, pass)) { } else {
int n_len = pass_tok - name_tok - 1; /* exclude space */ sess->state = ERR;
sess->uname = malloc(n_len + 1); sess->reason = EXIT;
strncpy(sess->uname, name_tok, n_len); return 1;
sess->uname[n_len] = 0;
priv_tok = strtok(NULL, " ");
sess->privileges = (char)atoi(priv_tok);
res = 1;
} }
fclose(fptr);
return res;
} }
// TODO: синхронизовать c C++ // TODO: синхронизовать c C++
+1 -1
View File
@@ -4,5 +4,5 @@
#include "main.h" #include "main.h"
int login(session *sess, char *pass); int login(session *sess, char *pass);
int process_error(session *sess); int process_error(session *sess);
long int find_user(char *uname); int process_user_name(char *uname, session *sess);
#endif #endif