-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.ts
138 lines (133 loc) · 4.11 KB
/
server.ts
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
129
130
131
132
133
134
135
136
137
138
"use strict";
import * as Koa from "koa";
import * as bodyParser from "koa-bodyparser";
import * as jsonSerializer from "koa-json";
import * as pino from "pino";
const log = pino({
level: process.env.NODE_ENV === "dev" ? "debug" :
(process.env.NODE_ENV === "test" ? "silent" : "info"),
});
import { readFile, writeFile } from "fs";
import { promisify } from "util";
const readFileAsync = promisify(readFile);
const writeFileAsync = promisify(writeFile);
import * as uuid from "uuid/v4";
const app = new Koa();
class ApiError extends Error {
public constructor(code: string, message: string) {
super(message);
this.name = code;
}
}
// tslint:disable-next-line:max-classes-per-file
class Store {
public users: string[] = [];
public push = async () =>
await writeFileAsync(`${__dirname}/store.json`, JSON.stringify(this.users), { encoding: "utf8" })
public pull = async () =>
this.users = JSON.parse(await readFileAsync(`${__dirname}/store.json`, { encoding: "utf8" }))
}
const store = new Store();
app.use(jsonSerializer({
pretty: false,
}));
app.use(async (ctx, next) => {
try {
await next();
ctx.status = 200;
ctx.body = { result: ctx.body };
} catch (err) {
log.error("an error occured", err, ctx, store.users);
if (err instanceof ApiError) {
ctx.status = 500;
ctx.body = {
error: {
code: err.name,
message: err.message,
},
};
} else {
log.error(err);
ctx.status = 500;
ctx.body = {
error: {
code: "INTERNAL_SERVER_ERROR",
message: "an error occured on the server",
},
};
}
}
});
app.use(bodyParser());
app.use(async (ctx, next) => {
if (ctx.request.method !== "POST") {
throw new ApiError("REQUEST_METHOD_MISMATCH", "api request method is not 'POST'");
} else if (!ctx.request.body || !ctx.request.body.function || !Array.isArray(ctx.request.body.parameters)) {
throw new ApiError("REQUEST_BODY_NOT_SENT", "request body is not valid");
} else if (ctx.request.body.version !== "Prometheus/1.0") {
throw new ApiError("API_VERSION_MISMATCH", "api version mismatches 'Prometheus/1.0'");
} else {
ctx.state = ctx.request.header.authorization ?
(ctx.request.header.authorization as string).substr(7) : undefined;
ctx.body = await next();
}
});
app.use(async (ctx) => {
switch (ctx.request.body.function) {
default: {
throw new ApiError("INVALID_FUNCTION", "function is not defined");
}
case "init_server": {
if (store.users.length > 0) {
throw new ApiError("ALREADY_INITIALIZED", "the lock has already been initialized");
} else {
const id = uuid();
store.users.push(id);
await store.push();
return id;
}
}
case "add_user": {
if (ctx.state && store.users.indexOf(ctx.state) >= 0) {
const id = uuid();
store.users.push(id);
await store.push();
return id;
} else {
throw new ApiError("NOT_AUTHENTICATED",
"permission not sufficient, either not logged in or not a valid user");
}
}
case "delete_user": {
if (ctx.state && store.users.indexOf(ctx.state) >= 0) {
if (ctx.request.body.parameters[0]) {
const index = store.users.indexOf(ctx.request.body.parameters[0]);
log.debug("deleting", index, store);
if (index < 0) {
throw new ApiError("USER_NOT_FOUND", "the specified user does not exists");
} else {
store.users.splice(index, 1);
await store.push();
return true;
}
} else {
throw new ApiError("INVALID_PARAMETERS", "parameters are invalid");
}
} else {
throw new ApiError("NOT_AUTHENTICATED",
"permission not sufficient, either not logged in or not a valid user");
}
}
}
});
export default app;
// tslint:disable-next-line:no-floating-promises
(async () => {
await store.pull();
app.listen(process.env.PORT || 3000);
log.info(`server listening on ${process.env.PORT || 3000}`);
})()
.catch((err) => {
log.error(err);
process.exit(1);
});