createTicket working, solves #3
This commit is contained in:
@@ -17,4 +17,4 @@ Both clients can:
|
|||||||
|
|
||||||
### Dependencies:
|
### Dependencies:
|
||||||
|
|
||||||
+ `libpqxx` for the API to the PostgreSQL database management system (official link: https://github.com/jtv/libpqxx)
|
+ `libcurl` for accessing the webserver
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
CC := g++
|
||||||
|
SRC := dao.cpp handler.cpp main.cpp parser.cpp printer.cpp json_serializer.cpp
|
||||||
|
FLAGS := -lcurl -g -Wall -Wextra
|
||||||
|
OUTDIR := ./build
|
||||||
|
OUT := tickets
|
||||||
|
|
||||||
|
build:
|
||||||
|
mkdir -p $(OUTDIR)
|
||||||
|
$(CC) -o $(OUTDIR)/$(OUT) $(SRC) $(FLAGS)
|
||||||
|
|
||||||
Executable
BIN
Binary file not shown.
+58
-7
@@ -1,19 +1,70 @@
|
|||||||
#include <cstdlib>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "include/dao.h"
|
#include "include/dao.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void Dao::populate_env() {
|
Dao::Dao() {
|
||||||
this->api_key = getenv("FRONTEND_API_KEY");
|
this->api_key = getenv("FRONTEND_API_KEY");
|
||||||
this->db_url = getenv("DB_URL");
|
if (this->api_key.empty()) {
|
||||||
|
cout << "FRONTEND_API_KEY environment variable is not set" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
this->base_url = getenv("BASE_API_URL");
|
||||||
|
if (this->base_url.empty()) {
|
||||||
|
cout << "BASE_API_URL environment variable is not set" << endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ticket_t Dao::fetch_ticket_create(string title, string description) {
|
static size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||||
|
size_t total = size * nmemb;
|
||||||
|
std::string* s = static_cast<std::string*>(userp);
|
||||||
|
s->append(static_cast<char*>(contents), total);
|
||||||
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ticket_t Dao::fetch_ticket_create(std::string title, std::string description) {
|
||||||
|
string response;
|
||||||
|
string url = this->base_url + "/tickets";
|
||||||
|
|
||||||
|
CURL *handle = curl_easy_init();
|
||||||
|
|
||||||
|
struct curl_slist* headers = nullptr;
|
||||||
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
|
headers = curl_slist_append(headers, ("Authorization: Bearer " + this->api_key).c_str());
|
||||||
|
|
||||||
|
string body = nlohmann::json{
|
||||||
|
{"title", title},
|
||||||
|
{"description", description}
|
||||||
|
}.dump();
|
||||||
|
|
||||||
|
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
curl_easy_setopt(handle, CURLOPT_POST, 1L);
|
||||||
|
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, body.c_str());
|
||||||
|
curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, static_cast<long>(body.size()));
|
||||||
|
|
||||||
|
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
|
||||||
|
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &response);
|
||||||
|
|
||||||
|
CURLcode rc = curl_easy_perform(handle);
|
||||||
|
|
||||||
|
curl_slist_free_all(headers);
|
||||||
|
curl_easy_cleanup(handle);
|
||||||
|
|
||||||
|
if (rc != CURLE_OK) {
|
||||||
|
throw std::runtime_error(std::string("curl_easy_perform failed: ") + curl_easy_strerror(rc));
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json j = nlohmann::json::parse(response);
|
||||||
|
|
||||||
|
ticket_t t = j.get<ticket_t>();
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
vector<ticket_t> Dao::fetch_ticket_get_all() {
|
vector<ticket_t> Dao::fetch_ticket_get_all() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-8
@@ -3,20 +3,22 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <curl/easy.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "ticket.h"
|
#include "ticket.h"
|
||||||
|
#include "json_serializer.h"
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class Dao {
|
class Dao {
|
||||||
public:
|
public:
|
||||||
string api_key;
|
std::string api_key;
|
||||||
string db_url;
|
std::string base_url;
|
||||||
void populate_env();
|
|
||||||
|
|
||||||
ticket_t fetch_ticket_create(string title, string description);
|
Dao();
|
||||||
vector<ticket_t> fetch_ticket_get_all();
|
ticket_t fetch_ticket_create(std::string title, std::string description);
|
||||||
vector<ticket_t> fetch_ticket_get_by_status(string status);
|
std::vector<ticket_t> fetch_ticket_get_all();
|
||||||
|
std::vector<ticket_t> fetch_ticket_get_by_status(std::string status);
|
||||||
ticket_t fetch_ticket_get_by_id(unsigned long id);
|
ticket_t fetch_ticket_get_by_id(unsigned long id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
#include "dao.h"
|
#include "dao.h"
|
||||||
|
|
||||||
using namespace std;
|
int handle_create(Dao *dao, std::string title, std::string description);
|
||||||
|
|
||||||
int handle_create(Dao *dao, string title, string description);
|
|
||||||
int handle_list(Dao *dao);
|
int handle_list(Dao *dao);
|
||||||
int handle_list(Dao *dao, string status);
|
int handle_list(Dao *dao, std::string status);
|
||||||
int handle_detail(Dao *dao, unsigned long id);
|
int handle_detail(Dao *dao, unsigned long id);
|
||||||
|
|
||||||
#endif // HANDLER_H
|
#endif // HANDLER_H
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "ticket.h"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
// Deserialize JSON -> class
|
||||||
|
void from_json(const json& j, ticket_t& t);
|
||||||
|
|
||||||
|
// Serialize class
|
||||||
|
void to_json(json& j, const ticket_t& t);
|
||||||
@@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
#include "ticket.h"
|
#include "ticket.h"
|
||||||
|
|
||||||
using namespace std;
|
void print_tickets(std::vector<ticket_t> tickets);
|
||||||
|
|
||||||
void print_tickets(vector<ticket_t> tickets);
|
|
||||||
|
|
||||||
#endif // PRINTER_H
|
#endif // PRINTER_H
|
||||||
@@ -2,17 +2,14 @@
|
|||||||
#define TICKET_H
|
#define TICKET_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned long id;
|
unsigned long id;
|
||||||
string title;
|
std::string title;
|
||||||
string description;
|
std::string description;
|
||||||
string status;
|
std::string status;
|
||||||
string created_at;
|
std::string created_at;
|
||||||
string updated_at;
|
std::string updated_at;
|
||||||
} ticket_t;
|
} ticket_t;
|
||||||
|
|
||||||
#endif // TICKET_H
|
#endif // TICKET_H
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include "include/json_serializer.h"
|
||||||
|
|
||||||
|
// Deserialize JSON -> class
|
||||||
|
void from_json(const json& j, ticket_t& t) {
|
||||||
|
t.id = j.at("id").get<int>();
|
||||||
|
t.title = j.at("title").get<std::string>();
|
||||||
|
t.description = j.at("description").get<std::string>();
|
||||||
|
t.status = j.at("status").get<std::string>();
|
||||||
|
t.created_at = j.at("created_at").get<std::string>();
|
||||||
|
t.updated_at = j.at("updated_at").get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize class -> JSON
|
||||||
|
void to_json(json& j, const ticket_t& t) {
|
||||||
|
j = json{
|
||||||
|
{"id", t.id},
|
||||||
|
{"title", t.title},
|
||||||
|
{"description", t.description},
|
||||||
|
{"status", t.status},
|
||||||
|
{"created_at", t.created_at},
|
||||||
|
{"updated_at", t.updated_at}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
int main(int argc, char *argv[], char *envp[]) {
|
int main(int argc, char *argv[], char *envp[]) {
|
||||||
Dao *dao = new Dao();
|
Dao *dao = new Dao();
|
||||||
dao->populate_env();
|
|
||||||
int retval = parse_args(dao, argc, argv);
|
int retval = parse_args(dao, argc, argv);
|
||||||
delete dao;
|
delete dao;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "include/printer.h"
|
#include "include/printer.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
void print_tickets(vector<ticket_t> tickets) {
|
void print_tickets(vector<ticket_t> tickets) {
|
||||||
for (ticket_t t : tickets) {
|
for (ticket_t t : tickets) {
|
||||||
cout << "/------+-------\n"
|
cout << "/------+-------\n"
|
||||||
|
|||||||
@@ -171,9 +171,9 @@ func createTicket(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
err = db.QueryRow(
|
err = db.QueryRow(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
"INSERT INTO tickets(title, description) VALUES($1, $2) RETURNING id;",
|
"INSERT INTO tickets(title, description) VALUES($1, $2) RETURNING id, status, created_at, updated_at;",
|
||||||
t.Title, t.Description,
|
t.Title, t.Description,
|
||||||
).Scan(&t.Id)
|
).Scan(&t.Id, &t.Status, &t.CreatedAt, &t.UpdatedAt)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
|
|||||||
Reference in New Issue
Block a user