diff options
| -rw-r--r-- | backend/src/API/ErrorDescription.zig | 3 | ||||
| -rw-r--r-- | backend/src/API/WeaponsAPI.zig | 49 | ||||
| -rw-r--r-- | backend/src/Database/Connection.zig | 1 | ||||
| -rw-r--r-- | backend/src/Database/RangedWeaponsAccessLayer.zig | 74 | ||||
| -rw-r--r-- | db/create_script.sql | 1 |
5 files changed, 123 insertions, 5 deletions
diff --git a/backend/src/API/ErrorDescription.zig b/backend/src/API/ErrorDescription.zig new file mode 100644 index 0000000..922eb6f --- /dev/null +++ b/backend/src/API/ErrorDescription.zig @@ -0,0 +1,3 @@ +pub const ErrorDescriptor = struct { + Message: []const u8 +}; diff --git a/backend/src/API/WeaponsAPI.zig b/backend/src/API/WeaponsAPI.zig index d095944..1b0ae00 100644 --- a/backend/src/API/WeaponsAPI.zig +++ b/backend/src/API/WeaponsAPI.zig @@ -2,12 +2,15 @@ const std = @import("std"); const httpz = @import("httpz"); const model = @import("../Models/RangedWeapon.zig"); const db = @import("../Database/Connection.zig"); +const errDesc = @import("ErrorDescription.zig"); pub fn RegisterEndpoints(router: *httpz.Router(void, *const fn (*httpz.request.Request, *httpz.response.Response) anyerror!void)) void { router.get("/weapons", testEndpoint, .{}); + router.get("/weapons/ranged", getAllRangedWeapons, .{}); router.post("/weapons/ranged", newRangedWeapon, .{}); router.get("/weapons/ranged/:id", getRangedWeaponById, .{}); - router.get("/weapons/ranged", getAllRangedWeapons, .{}); + router.put("/weapons/ranged/:id", updateRangedWeapon, .{}); + router.delete("/weapons/ranged/:id", deleteRangedWeapon, .{}); } fn testEndpoint(_: *httpz.Request, res: *httpz.Response) !void { @@ -57,9 +60,45 @@ fn getRangedWeaponById(req: *httpz.Request, res: *httpz.Response) !void { } fn newRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { - if (try req.json(model.RangedWeaponType)) |new| { - try res.json(new, .{}); + var body = try req.json(model.RangedWeaponType) orelse { + res.status = 400; + return; + }; + + db.RangedWeapons.Create(&body) catch |err| { + if (err == db.ResultErrors.AlreadyExists) { + res.status = 400; + try res.json(errDesc.ErrorDescriptor { + .Message = "A weapon with that ID already exists" + }, .{}); + return; + } + return err; + }; + + res.status = 201; +} + + +fn updateRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { + const id = req.param("id") orelse { + res.status = 400; + return; + }; + + var body = try req.json(model.RangedWeaponType) orelse { + res.status = 400; + return; + }; + + try db.RangedWeapons.Update(id, &body); +} + +fn deleteRangedWeapon(req: *httpz.Request, res: *httpz.Response) !void { + const id = req.param("id") orelse { + res.status = 400; return; - } - res.status = 502; + }; + + try db.RangedWeapons.Delete(id); } diff --git a/backend/src/Database/Connection.zig b/backend/src/Database/Connection.zig index 623165f..e08760c 100644 --- a/backend/src/Database/Connection.zig +++ b/backend/src/Database/Connection.zig @@ -4,6 +4,7 @@ const dotenv = @import("dotenv"); pub const ResultErrors = error { NotFound, + AlreadyExists }; pub var pool: *pg.Pool = undefined; diff --git a/backend/src/Database/RangedWeaponsAccessLayer.zig b/backend/src/Database/RangedWeaponsAccessLayer.zig index ca41197..ff75244 100644 --- a/backend/src/Database/RangedWeaponsAccessLayer.zig +++ b/backend/src/Database/RangedWeaponsAccessLayer.zig @@ -29,3 +29,77 @@ pub fn GetByDisplayName(allocator: std.mem.Allocator, displayName: []const u8) ! try row.deinit(); return outp; } + +pub fn Update(displayName: []const u8, updatedModel: *model.RangedWeaponType) !void { + const query = + \\ UPDATE RangedWeapons SET + \\ id = $1, + \\ name = $2, + \\ weapon_type = $3, + \\ accuracy = $4, + \\ concealability = $5, + \\ availability = $6, + \\ damage = $7, + \\ ammunition = $8, + \\ number_of_shots = $9, + \\ rate_of_fire = $10, + \\ reliability = $11, + \\ updated_at = CURRENT_TIMESTAMP + \\ WHERE id = $12 + ; + + _ = try conn.pool.exec(query, .{ + updatedModel.Id, + updatedModel.Name, + updatedModel.WeaponType, + updatedModel.Accuracy, + updatedModel.Concealability, + updatedModel.Avaliability, + updatedModel.Damage, + updatedModel.Ammunition, + updatedModel.NumberOfShots, + updatedModel.RateOfFire, + updatedModel.Reliability, + displayName, + }); +} + +pub fn Create(NewWeapon: *model.RangedWeaponType) !void { + if (try Exists(NewWeapon.Id)) return conn.ResultErrors.AlreadyExists; + const query = + \\ INSERT INTO RangedWeapons + \\ (id, name, weapon_type, accuracy, concealability, availability, damage, ammunition, number_of_shots, rate_of_fire, reliability) + \\ VALUES + \\ ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) + ; + + _ = try conn.pool.exec(query, .{ + NewWeapon.Id, + NewWeapon.Name, + NewWeapon.WeaponType, + NewWeapon.Accuracy, + NewWeapon.Concealability, + NewWeapon.Avaliability, + NewWeapon.Damage, + NewWeapon.Ammunition, + NewWeapon.NumberOfShots, + NewWeapon.RateOfFire, + NewWeapon.Reliability, + }); +} + +pub fn Exists(displayName: []const u8) !bool { + const query = "SELECT Id FROM RangedWeapons WHERE Id = $1"; + var row = try conn.pool.row(query, .{displayName}) orelse { + return false; + }; + try row.deinit(); + return true; +} + +pub fn Delete(displayName: []const u8) !void { + const query = "DELETE FROM RangedWeapons WHERE Id = $1"; + _ = try conn.pool.exec(query, .{ + displayName, + }); +} diff --git a/db/create_script.sql b/db/create_script.sql index 67f8c4c..5b016e6 100644 --- a/db/create_script.sql +++ b/db/create_script.sql @@ -13,3 +13,4 @@ CREATE TABLE RangedWeapons ( created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); + |
