Добавил:
ИВТ (советую зайти в "Несортированное") Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
30
Добавлен:
05.11.2024
Размер:
326.05 Кб
Скачать
    1. Задание 3.

      1. Доработка программного обеспечения – добавление аутентификации

Создайте две роли – «Ваши инициалы junior» и «Ваши инициалы admin». Junior обладает только правом чтения из базы данных, admin – полные права. Добавьте в программу поле ввода логина/пароля для подключения к базе данных от имени различных пользователей. Типы пользователей – администратор, пользователь.

-- Создание роли junior с правами на чтение данных

CREATE ROLE inicjunior LOGIN PASSWORD '123456';

GRANT CONNECT ON DATABASE students TO inicjunior;

GRANT USAGE ON SCHEMA public TO inicjunior;

GRANT SELECT ON ALL TABLES IN SCHEMA public TO inicjunior;

-- Обновление прав на будущие таблицы в схеме public для роли junior

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO inicjunior;

-- Создание роли admin с полными правами

CREATE ROLE inicadmin LOGIN PASSWORD '123456';

GRANT ALL PRIVILEGES ON DATABASE students TO inicadmin;

GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO inicadmin;

-- Обновление прав на будущие таблицы для роли admin

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO inicadmin;

Здесь inicjunior обладает правами только на чтение данных, а inicadmin — полными правами на чтение, запись и изменение данных.

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <libpq-fe.h>

/* Функция выхода из программы с сообщением об ошибке. */

void err_exit(PGconn *conn) {

PQfinish(conn);

exit(1);

}

/* Функция печати результата запроса на экран */

void print_query(PGresult *res) {

int rows = PQntuples(res);

int cols = PQnfields(res);

for(int i=0; i<rows; i++) {

for(int j=0; j<cols; j++) {

printf("%s ", PQgetvalue(res, i, j));

}

printf("\n");

}

}

/* Функция подключения к базе данных с аутентификацией */

PGconn* connect_db(const char* user, const char* password) {

char conninfo[256];

snprintf(conninfo, sizeof(conninfo), "user=%s password=%s dbname=students", user, password);

PGconn *conn = PQconnectdb(conninfo);

if (PQstatus(conn) == CONNECTION_BAD) {

fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));

PQfinish(conn);

exit(1);

}

return conn;

}

/* Функция для поиска самого младшего студента в указанной группе */

void find_youngest_student_in_group(PGconn *conn, const char* group_number) {

const char *param_values[1] = { group_number };

PGresult *res = PQexecParams(

conn,

"SELECT last_name, first_name, birthday "

"FROM youngest_student_in_group "

"WHERE students_group_number = $1 "

"LIMIT 1;",

1,

NULL,

param_values,

NULL,

NULL,

0

);

if (PQresultStatus(res) != PGRES_TUPLES_OK) {

fprintf(stderr, "No data retrieved\n");

PQclear(res);

err_exit(conn);

}

printf("Самый младший студент в группе %s:\n", group_number);

print_query(res);

PQclear(res);

}

int main() {

char username[50], password[50];

printf("Введите логин (inicadmin или inicjunior): ");

scanf("%49s", username);

printf("Введите пароль: ");

scanf("%49s", password);

PGconn *conn = connect_db(username, password);

char group_number[50];

printf("Введите номер группы (например, ИВТ-43): ");

scanf("%49s", group_number);

find_youngest_student_in_group(conn, group_number);

PQfinish(conn);

return 0;

}

 Программа запрашивает у пользователя логин и пароль и использует их для подключения к базе данных.

 В зависимости от роли (inicjunior или inicadmin) будут предоставлены различные уровни доступа.

  • inicjunior сможет только просматривать данные.

  • inicadmin имеет полный доступ, включая возможности модификации.

 Далее программа запрашивает номер группы, после чего выполняет запрос к представлению для вывода информации о самом младшем студенте из указанной группы.

      1. Доработка программного обеспечения – добавление CRUD операций

От имени администратора сделайте возможность добавлять, изменять и удалять значения оценок у любого студента.

От имени пользователя сделайте возможность выполнять запрос на просмотр всех его оценок и поиск конкретной строки по введенным значениям фамилии, имени и номера группы. Используя разработанную функцию, попробуйте выполнить SQL инъекцию на изменение значение оценки от имени данного пользователя.

GRANT SELECT ON TABLE field_comprehensions TO inicjunior;

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <libpq-fe.h>

// Функция выхода из программы с сообщением об ошибке

void err_exit(PGconn *conn) {

    PQfinish(conn);

    exit(1);

}

// Функция печати результата запроса на экран

void print_query(PGresult *res) {

    int rows = PQntuples(res);

    int cols = PQnfields(res);

    for (int i = 0; i < rows; i++) {

        for (int j = 0; j < cols; j++) {

            printf("%s ", PQgetvalue(res, i, j));

        }

        printf("\n");

    }

}

// Функция подключения к базе данных с аутентификацией

PGconn* connect_db(const char* user, const char* password) {

    char conninfo[256];

    snprintf(conninfo, sizeof(conninfo), "user=%s password=%s dbname=postgres", user, password);

    PGconn *conn = PQconnectdb(conninfo);

    if (PQstatus(conn) == CONNECTION_BAD) {

        fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));

        PQfinish(conn);

        exit(1);

    }

    return conn;

}

// Функция для получения field_id по названию дисциплины

char* get_field_id(PGconn *conn, const char* field_name) {

    const char *param_values[1] = { field_name };

    PGresult *res = PQexecParams(

        conn,

        "SELECT field_id FROM fields WHERE field_name = $1;",

        1,

        NULL,

        param_values,

        NULL,

        NULL,

        0

    );

    if (PQresultStatus(res) != PGRES_TUPLES_OK || PQntuples(res) == 0) {

        fprintf(stderr, "Field not found: %s\n", PQerrorMessage(conn));

        PQclear(res);

        return NULL; // Ошибка получения field_id

    }

    char *field_id = strdup(PQgetvalue(res, 0, 0)); // Используем strdup для копирования строки

    PQclear(res);

    return field_id; // Возвращаем строку

}

// Функция для добавления оценки

void add_grade(PGconn *conn, int student_id, const char* field_id, int mark) {

    char student_id_str[10];

    char mark_str[3];

    sprintf(student_id_str, "%d", student_id);

    sprintf(mark_str, "%d", mark);

    const char *param_values[3] = { student_id_str, field_id, mark_str }; // field_id передаётся как строка

    PGresult *res = PQexecParams(

        conn,

        "INSERT INTO field_comprehensions (student_id, field, mark) VALUES ($1, $2, $3);", // Изменено на 'field'

        3,

        NULL,

        param_values,

        NULL,

        NULL,

        0

    );

    if (PQresultStatus(res) != PGRES_COMMAND_OK) {

        fprintf(stderr, "Failed to add grade: %s\n", PQerrorMessage(conn));

        PQclear(res);

        err_exit(conn);

    }

    printf("Grade added successfully.\n");

    PQclear(res);

}

// Функция для обновления оценки

void update_grade(PGconn *conn, int student_id, const char* field_name, int new_mark) {

    char* field_id = get_field_id(conn, field_name);

    if (field_id == NULL) {

        fprintf(stderr, "Не удалось получить ID дисциплины.\n");

        return; // Прерываем выполнение, если ID не получен

    }

    // Преобразование student_id и new_mark в строковые форматы

    char student_id_str[10];

    sprintf(student_id_str, "%d", student_id);

   

    char new_mark_str[10];

    sprintf(new_mark_str, "%d", new_mark);

   

    const char *param_values[3] = { student_id_str, field_id, new_mark_str };

    PGresult *res = PQexecParams(

        conn,

        "UPDATE field_comprehensions SET mark = $3 WHERE student_id = $1 AND field = $2;", // Изменено на 'field'

        3,

        NULL,

        param_values,

        NULL,

        NULL,

        0

    );

    if (PQresultStatus(res) != PGRES_COMMAND_OK) {

        fprintf(stderr, "Failed to update grade: %s\n", PQerrorMessage(conn));

        PQclear(res);

        err_exit(conn);

    }

    printf("Grade updated successfully.\n");

    PQclear(res);

    free(field_id);

}

// Функция для удаления оценки

void delete_grade(PGconn *conn, int student_id, const char* field_id) {

    char student_id_str[10];

    sprintf(student_id_str, "%d", student_id);

    const char *param_values[2] = { student_id_str, field_id };

    PGresult *res = PQexecParams(

        conn,

        "DELETE FROM field_comprehensions WHERE student_id = $1 AND field = $2;", // Изменено на 'field'

        2,

        NULL,

        param_values,

        NULL,

        NULL,

        0

    );

    if (PQresultStatus(res) != PGRES_COMMAND_OK) {

        fprintf(stderr, "Failed to delete grade: %s\n", PQerrorMessage(conn));

        PQclear(res);

        err_exit(conn);

    }

    printf("Grade deleted successfully.\n");

    PQclear(res);

}

// Функция для просмотра всех оценок студента

void view_grades(PGconn *conn, int student_id) {

    char query[256];

    snprintf(query, sizeof(query),

        "SELECT f.field_name, fc.mark FROM field_comprehensions fc "

        "JOIN fields f ON fc.field = f.field_id "

        "WHERE fc.student_id = %d;", student_id);

   

    PGresult *res = PQexec(conn, query);

    if (PQresultStatus(res) != PGRES_TUPLES_OK) {

        fprintf(stderr, "Error executing query in view_grades: %s\n", PQerrorMessage(conn));

        PQclear(res);

        err_exit(conn);

    }

    printf("All grades for student %d:\n", student_id);

    print_query(res);

    PQclear(res);

}

// Функция для поиска оценок по имени, фамилии и номеру группы

void search_grades(PGconn *conn, const char* last_name, const char* first_name, const char* students_group_number) {

    const char *param_values[3] = { last_name, first_name, students_group_number };

    PGresult *res = PQexecParams(

        conn,

        "SELECT f.field_name, fc.mark FROM field_comprehensions fc "

        "JOIN students s ON fc.student_id = s.student_id "

        "JOIN fields f ON fc.field = f.field_id "

        "WHERE s.last_name = $1 AND s.first_name= $2 AND s.students_group_number = $3;",

        3,

        NULL,

        param_values,

        NULL,

        NULL,

        0

    );

    if (PQresultStatus(res) != PGRES_TUPLES_OK) {

        fprintf(stderr, "Error executing query in search_grades: %s\n", PQerrorMessage(conn));

        PQclear(res);

        err_exit(conn);

    }

    printf("Search results:\n");

    print_query(res);

    PQclear(res);

}

int main() {

    char username[50], password[50];

    printf("Введите логин (inicadmin или inicjunior): ");

    scanf("%49s", username);

    printf("Введите пароль: ");

    scanf("%49s", password);

    PGconn *conn = connect_db(username, password);

   

    if (strcmp(username, "inicadmin") == 0) {

        int option;

        printf("Admin Menu: 1-Add grade, 2-Update grade, 3-Delete grade\n");

        scanf("%d", &option);

        if (option == 1) {

            int student_id, mark;

            char field_name[50];

            printf("Введите ID студента (6 цифр): ");

            scanf("%d", &student_id);

            if (student_id < 100000 || student_id > 999999) {

                fprintf(stderr, "ID студента должно состоять из 6 цифр.\n");

                return 1;

            }

            printf("Введите название дисциплины: ");

            scanf(" %[^\n]", field_name);  // Считываем строку, включая пробелы

            printf("Введите оценку (от 1 до 5): ");

            scanf("%d", &mark);

            char* field_id = get_field_id(conn, field_name);

            if (field_id == NULL) {

                fprintf(stderr, "Не удалось получить ID дисциплины.\n");

                return 1;

            }

            add_grade(conn, student_id, field_id, mark);

            free(field_id); // Освобождаем выделенную память после использования

        } else if (option == 2) {

            int student_id, new_mark;

            char field_name[50];

            printf("Введите ID студента (6 цифр): ");

            scanf("%d", &student_id);

            if (student_id < 100000 || student_id > 999999) {

                fprintf(stderr, "ID студента должно состоять из 6 цифр.\n");

                return 1;

            }

            printf("Введите название дисциплины: ");

            scanf(" %[^\n]", field_name);  // Считываем строку, включая пробелы

            printf("Введите новую оценку (от 1 до 5): ");

            scanf("%d", &new_mark);

            update_grade(conn, student_id, field_name, new_mark);

        } else if (option == 3) {

            int student_id;

            char field_name[50];

            printf("Введите ID студента (6 цифр): ");

            scanf("%d", &student_id);

            if (student_id < 100000 || student_id > 999999) {

                fprintf(stderr, "ID студента должно состоять из 6 цифр.\n");

                return 1;

            }

            printf("Введите название дисциплины: ");

            scanf(" %[^\n]", field_name);  // Считываем строку, включая пробелы

            char* field_id = get_field_id(conn, field_name);

            if (field_id == NULL) {

                fprintf(stderr, "Не удалось получить ID дисциплины.\n");

                return 1;

            }

            delete_grade(conn, student_id, field_id);

            free(field_id); // Освобождаем выделенную память после использования

        }

    } else if (strcmp(username, "inicjunior") == 0) {

        int student_id;

        printf("Введите ID студента (6 цифр): ");

        scanf("%d", &student_id);

        if (student_id < 100000 || student_id > 999999) {

            fprintf(stderr, "ID студента должно состоять из 6 цифр.\n");

            return 1;

        }

        view_grades(conn, student_id);

        char surname[50], name[50], group[50];

        printf("Введите фамилию: ");

        scanf("%49s", surname);

        printf("Введите имя: ");

        scanf("%49s", name);

        printf("Введите номер группы: ");

        scanf("%49s", group);

        search_grades(conn, surname, name, group);

    }

    PQfinish(conn);

    return 0;

}

SELECT f.mark

FROM fields f

JOIN field_comprehensions fc ON f.field_id = fc.field

WHERE fc.student_id = 812850 AND f.field_name = 'Философия';

Соседние файлы в папке 8 laba
  • #
    05.11.20244.09 Кб182.2
  • #
    05.11.20244.02 Кб162.3
  • #
    05.11.2024326.05 Кб308 лаба.docx
  • #
    05.11.202428.19 Кб19main
  • #
    05.11.202410.84 Кб17main.c
  • #
    05.11.2024157 б16Makefile
  • #
    05.11.20243.35 Кб17zad1.1
  • #
    05.11.20242.56 Кб17zad2.1