Compare commits
2 Commits
ed942060a2
...
3464f32c46
| Author | SHA1 | Date | |
|---|---|---|---|
| 3464f32c46 | |||
| 3e9d61b8c6 |
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/auth/login"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/login"
|
||||
headers:
|
||||
- name: Content-Type
|
||||
value: application/json
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/auth/token"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/token"
|
||||
headers:
|
||||
- name: Cookie
|
||||
value: "{{REFRESH_COOKIE}}"
|
||||
|
||||
@@ -2,3 +2,8 @@ info:
|
||||
name: Auth
|
||||
type: folder
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: auth
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/collection/{{CollectionID}}/add"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{CollectionID}}/add"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/collection"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: "{{BASE_URL}}/api/collection/{{CollectionID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{CollectionID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,11 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/collection/{{CollectionID}}"
|
||||
params:
|
||||
- name: ""
|
||||
value: ""
|
||||
type: query
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{CollectionID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,15 +5,15 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/collection/list/{{PageSize}}/{{Page}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/list/{{PageSize}}/{{Page}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
variables:
|
||||
- name: PageSize
|
||||
value: "1"
|
||||
value: "5"
|
||||
- name: Page
|
||||
value: "0"
|
||||
value: "1"
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/collection/{{CollectionID}}/remove"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{CollectionID}}/remove"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: PATCH
|
||||
url: "{{BASE_URL}}/api/collection/{{CollectionID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{CollectionID}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
info:
|
||||
name: Collections
|
||||
type: folder
|
||||
seq: 6
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: collections
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/game"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: "{{BASE_URL}}/api/game/{{GameID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{GameID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/game/{{GameID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{GameID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/game/search/{{Query}}/{{PageSize}}/{{Page}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/search/{{Query}}/{{PageSize}}/{{Page}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
@@ -13,9 +13,9 @@ runtime:
|
||||
- name: Query
|
||||
value: test
|
||||
- name: PageSize
|
||||
value: "2"
|
||||
value: "5"
|
||||
- name: Page
|
||||
value: "2"
|
||||
value: "1"
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: PATCH
|
||||
url: "{{BASE_URL}}/api/game/{{GameID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{GameID}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
info:
|
||||
name: Game
|
||||
type: folder
|
||||
seq: 4
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: games
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/invite/accept"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/accept"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/invite"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,3 +5,6 @@ info:
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: invites
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/player"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: "{{BASE_URL}}/api/player/{{PlayerID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{PlayerID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/player/{{PlayerID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{PlayerID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,9 +5,16 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/player/list"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/list/{{PageSize}}/{{Page}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
variables:
|
||||
- name: PageSize
|
||||
value: "100"
|
||||
- name: Page
|
||||
value: "1"
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: PATCH
|
||||
url: "{{BASE_URL}}/api/player/{{PlayerID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{PlayerID}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
info:
|
||||
name: Players
|
||||
type: folder
|
||||
seq: 2
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: players
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BASE_URL}}/api/user"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: DELETE
|
||||
url: "{{BASE_URL}}/api/user/{{UserID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{UserID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: GET
|
||||
url: "{{BASE_URL}}/api/user/{{UserID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{UserID}}"
|
||||
auth: inherit
|
||||
|
||||
runtime:
|
||||
|
||||
@@ -5,7 +5,7 @@ info:
|
||||
|
||||
http:
|
||||
method: PATCH
|
||||
url: "{{BASE_URL}}/api/user/{{UserID}}"
|
||||
url: "{{BASE_URL}}/{{SECTOR}}/{{UserID}}"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
info:
|
||||
name: User
|
||||
type: folder
|
||||
seq: 3
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
variables:
|
||||
- name: SECTOR
|
||||
value: users
|
||||
|
||||
@@ -5,4 +5,4 @@ variables:
|
||||
- name: REFRESH_COOKIE
|
||||
value: ""
|
||||
- name: BASE_URL
|
||||
value: http://localhost:3000
|
||||
value: http://localhost:3000/api
|
||||
|
||||
@@ -23,7 +23,7 @@ async function login(request: UnwrappedRequest<LoginRequest>): Promise<Response>
|
||||
u: verify.userId.raw,
|
||||
r: verify.refreshCount,
|
||||
},
|
||||
process.env.JWT_SECRET_KEY as string,
|
||||
process.env.JWT_REFRESH_KEY as string,
|
||||
{ expiresIn: `${tokenLifeSpanInDays * 24}h` },
|
||||
);
|
||||
const cookies = request?.request?.cookies;
|
||||
@@ -52,7 +52,7 @@ async function token(request: UnwrappedRequest): Promise<Response> {
|
||||
const refreshToken: {
|
||||
u: string;
|
||||
r: string;
|
||||
} = jwt.verify(refreshCookie, process.env.JWT_SECRET_KEY as string) as { u: string; r: string };
|
||||
} = jwt.verify(refreshCookie, process.env.JWT_REFRESH_KEY as string) as { u: string; r: string };
|
||||
|
||||
if (!(await orm.users.verifyRefreshCount(UserId.fromID(refreshToken.u), refreshToken.r))) {
|
||||
const response = new UnauthorizedResponse('Invalid refresh token');
|
||||
|
||||
21
src/index.ts
21
src/index.ts
@@ -5,21 +5,24 @@ import players from './routes/players';
|
||||
import games from './routes/games';
|
||||
import invites from './routes/invites';
|
||||
import collections from './routes/collections';
|
||||
import { buildRoute } from './utilities/routeBuilder';
|
||||
|
||||
const server = Bun.serve({
|
||||
routes: {
|
||||
...auth,
|
||||
...users,
|
||||
...players,
|
||||
...games,
|
||||
...invites,
|
||||
...collections,
|
||||
'/test': {
|
||||
routes: buildRoute({
|
||||
[process.env.API_ROOT_PATH ?? '']:{
|
||||
auth,
|
||||
users,
|
||||
players,
|
||||
games,
|
||||
invites,
|
||||
collections,
|
||||
},
|
||||
'test': {
|
||||
GET: () => {
|
||||
return new OkResponse();
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as any,
|
||||
|
||||
// (optional) fallback for unmatched routes:
|
||||
fetch(): Response {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { sql } from 'bun';
|
||||
import { ClaimDefinition } from '../utilities/claimDefinitions';
|
||||
import { SecureId, UserId } from '../utilities/secureIds';
|
||||
import { UserId } from '../utilities/secureIds';
|
||||
|
||||
export class Claims extends ClaimDefinition {
|
||||
userId?: UserId;
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import { guard, unwrapMethod } from '../utilities/guard';
|
||||
import auth from '../endpoints/auth';
|
||||
import { OkResponse } from '../utilities/responseHelper';
|
||||
import { Claims } from '../orm/claims';
|
||||
|
||||
export default {
|
||||
'/api/auth/login': {
|
||||
login: {
|
||||
POST: unwrapMethod(auth.login),
|
||||
},
|
||||
'/api/auth/token': {
|
||||
token: {
|
||||
GET: unwrapMethod(auth.token),
|
||||
},
|
||||
'/api/auth/logout': {
|
||||
logout: {
|
||||
POST: unwrapMethod(auth.logout),
|
||||
},
|
||||
'/api/auth/changePassword/:id': {
|
||||
changePassword: {
|
||||
':id': {
|
||||
PATCH: guard(auth.changePassword, [Claims.ADMIN, Claims.USERS.SELF.UPDATE]),
|
||||
},
|
||||
'/api/auth/test': {
|
||||
GET: () => new OkResponse(),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,29 +3,28 @@ import { Claims } from '../orm/claims';
|
||||
import collections from '../endpoints/collections';
|
||||
|
||||
export default {
|
||||
'/api/collection': {
|
||||
POST: guard(collections.create, [Claims.ADMIN, Claims.COLLECTIONS.CREATE]),
|
||||
},
|
||||
'/api/collection/:id': {
|
||||
'POST': guard(collections.create, [Claims.ADMIN, Claims.COLLECTIONS.CREATE]),
|
||||
':id': {
|
||||
GET: guard(collections.get, [Claims.ADMIN, Claims.COLLECTIONS.UNOWNED.READ, Claims.COLLECTIONS.OWNED.READ]),
|
||||
// PATCH: guard(collections.update, [Claims.ADMIN, Claims.PLAYERS.OTHER.UPDATE, Claims.PLAYERS.SELF.UPDATE]),
|
||||
// DELETE: guard(collections.drop, [Claims.ADMIN, Claims.PLAYERS.OTHER.DELETE, Claims.PLAYERS.SELF.DELETE]),
|
||||
},
|
||||
'/api/collection/:id/add': {
|
||||
PATCH: guard(collections.update, [Claims.ADMIN, Claims.PLAYERS.OTHER.UPDATE, Claims.PLAYERS.SELF.UPDATE]),
|
||||
DELETE: guard(collections.drop, [Claims.ADMIN, Claims.PLAYERS.OTHER.DELETE, Claims.PLAYERS.SELF.DELETE]),
|
||||
add: {
|
||||
POST: guard(collections.addGame, [
|
||||
Claims.ADMIN,
|
||||
Claims.COLLECTIONS.UNOWNED.GAME.ADD,
|
||||
Claims.COLLECTIONS.OWNED.GAME.ADD,
|
||||
]),
|
||||
},
|
||||
'/api/collection/:id/remove': {
|
||||
remove: {
|
||||
POST: guard(collections.removeGame, [
|
||||
Claims.ADMIN,
|
||||
Claims.COLLECTIONS.UNOWNED.GAME.REMOVE,
|
||||
Claims.COLLECTIONS.OWNED.GAME.REMOVE,
|
||||
]),
|
||||
},
|
||||
'/api/collection/list/:pageSize/:page': {
|
||||
},
|
||||
'list': {
|
||||
variants: [':pageSize/:page', ':page'],
|
||||
GET: guard(collections.list, [Claims.ADMIN, Claims.COLLECTIONS.OWNED.LIST]),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,15 +3,16 @@ import { Claims } from '../orm/claims';
|
||||
import games from '../endpoints/games';
|
||||
|
||||
export default {
|
||||
'/api/game': {
|
||||
POST: guard(games.create, [Claims.ADMIN, Claims.GAMES.CREATE]),
|
||||
},
|
||||
'/api/game/:id': {
|
||||
'POST': guard(games.create, [Claims.ADMIN, Claims.GAMES.CREATE]),
|
||||
':id': {
|
||||
GET: guard(games.get, [Claims.ADMIN, Claims.GAMES.READ]),
|
||||
PATCH: guard(games.update, [Claims.ADMIN, Claims.GAMES.UPDATE]),
|
||||
DELETE: guard(games.drop, [Claims.ADMIN, Claims.GAMES.DELETE]),
|
||||
},
|
||||
'/api/game/search/:query/:pageSize/:page': {
|
||||
'search': {
|
||||
':query': {
|
||||
variants: [':pageSize/:page', ':page'],
|
||||
GET: guard(games.query, [Claims.ADMIN, Claims.GAMES.READ]),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,10 +3,8 @@ import { Claims } from '../orm/claims';
|
||||
import invite from '../endpoints/invites';
|
||||
|
||||
export default {
|
||||
'/api/invite': {
|
||||
POST: guard(invite.create, [Claims.ADMIN, Claims.USERS.INVITE]),
|
||||
},
|
||||
'/api/invite/accept': {
|
||||
accept: {
|
||||
POST: unwrapMethod(invite.accept),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,15 +3,14 @@ import { Claims } from '../orm/claims';
|
||||
import player from '../endpoints/players';
|
||||
|
||||
export default {
|
||||
'/api/player': {
|
||||
POST: guard(player.create, [Claims.ADMIN, Claims.PLAYERS.CREATE]),
|
||||
},
|
||||
'/api/player/:id': {
|
||||
'POST': guard(player.create, [Claims.ADMIN, Claims.PLAYERS.CREATE]),
|
||||
':id': {
|
||||
GET: guard(player.get, [Claims.ADMIN, Claims.PLAYERS.OTHER.READ, Claims.PLAYERS.SELF.READ]),
|
||||
PATCH: guard(player.update, [Claims.ADMIN, Claims.PLAYERS.OTHER.UPDATE, Claims.PLAYERS.SELF.UPDATE]),
|
||||
DELETE: guard(player.drop, [Claims.ADMIN, Claims.PLAYERS.OTHER.DELETE, Claims.PLAYERS.SELF.DELETE]),
|
||||
},
|
||||
'/api/player/list/:pageSize/:page': {
|
||||
'list': {
|
||||
variants: [':pageSize/:page', ':page'],
|
||||
GET: guard(player.list, [Claims.ADMIN, Claims.PLAYERS.OTHER.READ]),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,10 +3,8 @@ import user from '../endpoints/users';
|
||||
import { Claims } from '../orm/claims';
|
||||
|
||||
export default {
|
||||
'/api/user': {
|
||||
POST: guard(user.create, [Claims.ADMIN, Claims.USERS.CREATE]),
|
||||
},
|
||||
'/api/user/:id': {
|
||||
'POST': guard(user.create, [Claims.ADMIN, Claims.USERS.CREATE]),
|
||||
':id': {
|
||||
GET: guard(user.get, [Claims.ADMIN, Claims.USERS.OTHER.READ, Claims.USERS.SELF.READ]),
|
||||
PATCH: guard(user.update, [Claims.ADMIN, Claims.USERS.OTHER.UPDATE, Claims.USERS.SELF.UPDATE]),
|
||||
DELETE: guard(user.drop, [Claims.ADMIN, Claims.USERS.OTHER.UPDATE, Claims.USERS.SELF.UPDATE]),
|
||||
|
||||
41
src/utilities/routeBuilder.ts
Normal file
41
src/utilities/routeBuilder.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export function buildRoute(
|
||||
route: any,
|
||||
currentPath: string = '',
|
||||
): {
|
||||
[x: string]: {
|
||||
POST?: Function;
|
||||
GET?: Function;
|
||||
PUT?: Function;
|
||||
DELETE?: Function;
|
||||
};
|
||||
} {
|
||||
let returnValue: { [x: string]: any } = {};
|
||||
|
||||
const keys = Object.keys(route);
|
||||
for (let i in keys) {
|
||||
const key = keys[i];
|
||||
if (key === 'POST' || key === 'GET' || key === 'PUT' || key === 'DELETE' || key === 'variants') {
|
||||
continue;
|
||||
}
|
||||
returnValue = {
|
||||
...returnValue,
|
||||
...buildRoute(route[key], `${currentPath}/${key}`),
|
||||
};
|
||||
}
|
||||
|
||||
if (route.variants || route.POST || route.GET || route.PUT || route.DELETE) {
|
||||
const variants: string[] = route.variants ?? [];
|
||||
const endpointDefinition = {
|
||||
POST: route.POST,
|
||||
GET: route.GET,
|
||||
PUT: route.PUT,
|
||||
DELETE: route.DELETE,
|
||||
};
|
||||
returnValue[currentPath] = endpointDefinition;
|
||||
for (let key in variants) {
|
||||
returnValue[`${currentPath}/${variants[key]}`] = endpointDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
Reference in New Issue
Block a user