summaryrefslogtreecommitdiff
path: root/backend/src/API/AuthenticationAPI.zig
blob: 82cdb1c1c6df96f3aff95e3b0ec84d2b688ca84e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const std = @import("std");
const httpz = @import("httpz");
const model = @import("../Models/User.zig");
const db = @import("../Database/Connection.zig");
const errDesc = @import("ErrorDescription.zig");
const Handler = @import("../Handler.zig");
const Tokens = @import("../Authentication/Tokens.zig");

pub fn RegisterEndpoints(router: *httpz.Router(*Handler.Handler,*const fn (*Handler.RequestData, *httpz.request.Request, *httpz.response.Response) anyerror!void)) void {
    router.get("/auth", getUser, .{});
    router.post("/auth/register", register, .{});
    router.post("/auth/login", login, .{});
}

fn getUser(data: *Handler.RequestData, _: *httpz.Request, res: *httpz.Response) !void { 
    if (data.User == null) {
        try res.json(.{.status = "Unauthnticated"}, .{});
        return;
    }
    try res.json(.{ 
        .Username = data.User.?.Username,
        .Role = data.User.?.Role,
    }, .{});
}

const authResult = struct {
    Token: []const u8,
    User: struct {
        Username: []const u8,
        Role: []const u8
    },
};

fn register(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
    var body = try req.json(model.RequestBody) orelse {
        res.setStatus(.bad_request);
        return;
    };

    var body_model = try body.ToModel(req.arena);

    db.Users.Create(&body_model) catch |err| {
        if (err == db.ResultErrors.AlreadyExists) {
            res.setStatus(.bad_request);
            try res.json(errDesc.AlreadyExistsDescriptor, .{});
            return;
        }
        res.setStatus(.internal_server_error);
        return;
    };

    const loginResult = loginAction(req.arena, body) catch |err| {
        if (err == db.ResultErrors.NotFound) {
            res.setStatus(.unauthorized);
            try res.json(errDesc.ErrorDescriptor {
                .Message = "Login or password is incorrect"
            }, .{});
            return;
        }
        return err;
    };

    try res.json(loginResult, .{});
    res.setStatus(.created);
}

fn login(_: *Handler.RequestData, req: *httpz.Request, res: *httpz.Response) !void {
    const body = try req.json(model.RequestBody) orelse {
        res.setStatus(.bad_request);
        return;
    };

    const username = body.Username;
    const pwd = body.Password;

    const user = db.Users.GetByCredentials(req.arena, username, pwd) catch |err| {
        if (err == db.ResultErrors.NotFound) {
            res.setStatus(.unauthorized);
            try res.json(errDesc.ErrorDescriptor {
                .Message = "Login or password is incorrect"
            }, .{});
            return;
        }
        return err;
    };

    const token = try Tokens.GenerateNewSession(res.arena, user);
    try res.json(.{ 
        .Token = token,
        .User = .{
            .Username = user.Username,
            .Role = user.Role.ToString(),
        },
    } , .{});
}

/// Logs in with the given credentials
fn loginAction(allocator: std.mem.Allocator, requetsed: model.RequestBody) !authResult {
    const username = requetsed.Username;
    const pwd = requetsed.Password;
    const user = try db.Users.GetByCredentials(allocator, username, pwd); // catch |err| {
        // if (err == db.ResultErrors.NotFound) {
            // res.setStatus(.unauthorized);
            // try res.json(errDesc.ErrorDescriptor {
                // .Message = "Login or password is incorrect"
            // }, .{});
            // return;
        // }
        // return err;
    // };

    const token = try Tokens.GenerateNewSession(allocator, user);

    return authResult {
        .Token = token,
        .User = .{
            .Username = user.Username,
            .Role = user.Role.ToString(),
        }
    };
    // try res.json(.{ 
        // .Token = token,
        // .User = .{
            // .Username = user.Username,
            // .Role = user.Role.ToString(),
        // },
    // } , .{});
}