rhythia-api 151.0.0 → 152.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/approveMap.ts +3 -1
- package/api/createBeatmap.ts +3 -1
- package/api/createBeatmapPage.ts +4 -2
- package/api/deleteBeatmapPage.ts +3 -1
- package/api/editAboutMe.ts +3 -1
- package/api/editProfile.ts +3 -1
- package/api/getAvatarUploadUrl.ts +3 -1
- package/api/getBadgedUsers.ts +1 -1
- package/api/getLeaderboard.ts +5 -3
- package/api/getMapUploadUrl.ts +3 -1
- package/api/getPassToken.ts +56 -0
- package/api/nominateMap.ts +3 -1
- package/api/postBeatmapComment.ts +3 -1
- package/api/rankMapsArchive.ts +3 -1
- package/api/setPasskey.ts +60 -0
- package/api/submitScore.ts +25 -7
- package/api/updateBeatmapPage.ts +3 -1
- package/index.ts +38 -0
- package/package.json +2 -1
- package/types/database.ts +26 -0
- package/utils/getUserBySession.ts +37 -0
- package/utils/requestUtils.ts +3 -15
- package/utils/security.ts +20 -0
- package/utils/star-calc/index.ts +0 -2
package/api/approveMap.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -23,7 +25,7 @@ export async function POST(request: Request) {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
26
|
-
const user = (await
|
|
28
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
27
29
|
let { data: queryUserData, error: userError } = await supabase
|
|
28
30
|
.from("profiles")
|
|
29
31
|
.select("*")
|
package/api/createBeatmap.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { SSPMParser } from "../utils/star-calc/sspmParser";
|
|
|
5
5
|
import { supabase } from "../utils/supabase";
|
|
6
6
|
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
7
7
|
import { rateMap } from "../utils/star-calc";
|
|
8
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
9
|
+
import { User } from "@supabase/supabase-js";
|
|
8
10
|
const s3Client = new S3Client({
|
|
9
11
|
region: "auto",
|
|
10
12
|
endpoint: "https://s3.eu-central-003.backblazeb2.com",
|
|
@@ -52,7 +54,7 @@ export async function handler({
|
|
|
52
54
|
const parsedData = parser.parse();
|
|
53
55
|
const digested = parsedData.strings.mapID;
|
|
54
56
|
|
|
55
|
-
const user = (await
|
|
57
|
+
const user = (await getUserBySession(session)) as User;
|
|
56
58
|
let { data: userData, error: userError } = await supabase
|
|
57
59
|
.from("profiles")
|
|
58
60
|
.select("*")
|
package/api/createBeatmapPage.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -27,7 +29,7 @@ export async function handler({
|
|
|
27
29
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
28
30
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
29
31
|
> {
|
|
30
|
-
const user = (await
|
|
32
|
+
const user = (await getUserBySession(session)) as User;
|
|
31
33
|
let { data: userData, error: userError } = await supabase
|
|
32
34
|
.from("profiles")
|
|
33
35
|
.select("*")
|
|
@@ -49,7 +51,7 @@ export async function handler({
|
|
|
49
51
|
{ status: 404 }
|
|
50
52
|
);
|
|
51
53
|
}
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
const upserted = await supabase
|
|
54
56
|
.from("beatmapPages")
|
|
55
57
|
.upsert({
|
package/api/deleteBeatmapPage.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -28,7 +30,7 @@ export async function handler({
|
|
|
28
30
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
29
31
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
30
32
|
> {
|
|
31
|
-
const user = (await
|
|
33
|
+
const user = (await getUserBySession(session)) as User;
|
|
32
34
|
let { data: userData, error: userError } = await supabase
|
|
33
35
|
.from("profiles")
|
|
34
36
|
.select("*")
|
package/api/editAboutMe.ts
CHANGED
|
@@ -3,6 +3,8 @@ import z from "zod";
|
|
|
3
3
|
import { Database } from "../types/database";
|
|
4
4
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
5
5
|
import { supabase } from "../utils/supabase";
|
|
6
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
7
|
+
import { User } from "@supabase/supabase-js";
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
8
10
|
session: z.string(),
|
|
@@ -45,7 +47,7 @@ export async function handler(
|
|
|
45
47
|
);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
const user = (await
|
|
50
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
49
51
|
let userData: Database["public"]["Tables"]["profiles"]["Update"];
|
|
50
52
|
|
|
51
53
|
// Find user's entry
|
package/api/editProfile.ts
CHANGED
|
@@ -3,6 +3,8 @@ import z from "zod";
|
|
|
3
3
|
import { Database } from "../types/database";
|
|
4
4
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
5
5
|
import { supabase } from "../utils/supabase";
|
|
6
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
7
|
+
import { User } from "@supabase/supabase-js";
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
8
10
|
session: z.string(),
|
|
@@ -46,7 +48,7 @@ export async function handler(
|
|
|
46
48
|
);
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
const user = (await
|
|
51
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
50
52
|
|
|
51
53
|
let userData: Database["public"]["Tables"]["profiles"]["Update"];
|
|
52
54
|
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from "@aws-sdk/client-s3";
|
|
11
11
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
12
12
|
import { validateIntrinsicToken } from "../utils/validateToken";
|
|
13
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
14
|
+
import { User } from "@supabase/supabase-js";
|
|
13
15
|
|
|
14
16
|
const s3Client = new S3Client({
|
|
15
17
|
region: "auto",
|
|
@@ -51,7 +53,7 @@ export async function handler({
|
|
|
51
53
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
52
54
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
53
55
|
> {
|
|
54
|
-
const user = (await
|
|
56
|
+
const user = (await getUserBySession(session)) as User;
|
|
55
57
|
|
|
56
58
|
if (!validateIntrinsicToken(intrinsicToken)) {
|
|
57
59
|
return NextResponse.json({
|
package/api/getBadgedUsers.ts
CHANGED
package/api/getLeaderboard.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import z from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { protectedApi } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -48,7 +50,7 @@ export async function handler(
|
|
|
48
50
|
const VIEW_PER_PAGE = 50;
|
|
49
51
|
|
|
50
52
|
export async function getLeaderboard(page = 1, session: string) {
|
|
51
|
-
const getUserData = await
|
|
53
|
+
const getUserData = (await getUserBySession(session)) as User;
|
|
52
54
|
|
|
53
55
|
let leaderPosition = 0;
|
|
54
56
|
|
|
@@ -56,7 +58,7 @@ export async function getLeaderboard(page = 1, session: string) {
|
|
|
56
58
|
let { data: queryData, error } = await supabase
|
|
57
59
|
.from("profiles")
|
|
58
60
|
.select("*")
|
|
59
|
-
.eq("uid", getUserData.
|
|
61
|
+
.eq("uid", getUserData.id)
|
|
60
62
|
.single();
|
|
61
63
|
|
|
62
64
|
if (queryData) {
|
package/api/getMapUploadUrl.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from "@aws-sdk/client-s3";
|
|
11
11
|
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
12
12
|
import { validateIntrinsicToken } from "../utils/validateToken";
|
|
13
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
14
|
+
import { User } from "@supabase/supabase-js";
|
|
13
15
|
|
|
14
16
|
const s3Client = new S3Client({
|
|
15
17
|
region: "auto",
|
|
@@ -53,7 +55,7 @@ export async function handler({
|
|
|
53
55
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
54
56
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
55
57
|
> {
|
|
56
|
-
const user = (await
|
|
58
|
+
const user = (await getUserBySession(session)) as User;
|
|
57
59
|
|
|
58
60
|
if (!validateIntrinsicToken(intrinsicToken)) {
|
|
59
61
|
return NextResponse.json({
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { Database } from "../types/database";
|
|
4
|
+
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
5
|
+
import { supabase } from "../utils/supabase";
|
|
6
|
+
import md5 from "md5";
|
|
7
|
+
import { encryptString } from "../utils/security";
|
|
8
|
+
export const Schema = {
|
|
9
|
+
input: z.strictObject({
|
|
10
|
+
data: z.object({
|
|
11
|
+
email: z.string(),
|
|
12
|
+
passkey: z.string(),
|
|
13
|
+
computerName: z.string(),
|
|
14
|
+
}),
|
|
15
|
+
}),
|
|
16
|
+
output: z.object({
|
|
17
|
+
token: z.string().optional(),
|
|
18
|
+
error: z.string().optional(),
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export async function POST(request: Request): Promise<NextResponse> {
|
|
23
|
+
return protectedApi({
|
|
24
|
+
request,
|
|
25
|
+
schema: Schema,
|
|
26
|
+
authorization: () => {},
|
|
27
|
+
activity: handler,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function handler(
|
|
32
|
+
data: (typeof Schema)["input"]["_type"]
|
|
33
|
+
): Promise<NextResponse<(typeof Schema)["output"]["_type"]>> {
|
|
34
|
+
let { data: queryPasskey, error } = await supabase
|
|
35
|
+
.from("passkeys")
|
|
36
|
+
.select("*")
|
|
37
|
+
.eq("email", data.data.email)
|
|
38
|
+
.eq("passkey", data.data.passkey)
|
|
39
|
+
.single();
|
|
40
|
+
|
|
41
|
+
if (!queryPasskey) {
|
|
42
|
+
return NextResponse.json({
|
|
43
|
+
error: "Wrong combination",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return NextResponse.json({
|
|
47
|
+
token: encryptString(
|
|
48
|
+
JSON.stringify({
|
|
49
|
+
userId: queryPasskey.id,
|
|
50
|
+
email: queryPasskey.email,
|
|
51
|
+
passKey: queryPasskey.passkey,
|
|
52
|
+
computerName: data.data.computerName,
|
|
53
|
+
})
|
|
54
|
+
),
|
|
55
|
+
});
|
|
56
|
+
}
|
package/api/nominateMap.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -23,7 +25,7 @@ export async function POST(request: Request) {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
26
|
-
const user = (await
|
|
28
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
27
29
|
let { data: queryUserData, error: userError } = await supabase
|
|
28
30
|
.from("profiles")
|
|
29
31
|
.select("*")
|
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { User } from "@supabase/supabase-js";
|
|
6
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -30,7 +32,7 @@ export async function handler({
|
|
|
30
32
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
31
33
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
32
34
|
> {
|
|
33
|
-
const user = (await
|
|
35
|
+
const user = (await getUserBySession(session)) as User;
|
|
34
36
|
let { data: userData, error: userError } = await supabase
|
|
35
37
|
.from("profiles")
|
|
36
38
|
.select("*")
|
package/api/rankMapsArchive.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -23,7 +25,7 @@ export async function POST(request: Request) {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export async function handler(data: (typeof Schema)["input"]["_type"]) {
|
|
26
|
-
const user = (await
|
|
28
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
27
29
|
let { data: queryUserData, error: userError } = await supabase
|
|
28
30
|
.from("profiles")
|
|
29
31
|
.select("*")
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { Database } from "../types/database";
|
|
4
|
+
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
5
|
+
import { supabase } from "../utils/supabase";
|
|
6
|
+
import md5 from "md5";
|
|
7
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
8
|
+
import { User } from "@supabase/supabase-js";
|
|
9
|
+
export const Schema = {
|
|
10
|
+
input: z.strictObject({
|
|
11
|
+
session: z.string(),
|
|
12
|
+
data: z.object({
|
|
13
|
+
passkey: z.string(),
|
|
14
|
+
}),
|
|
15
|
+
}),
|
|
16
|
+
output: z.object({
|
|
17
|
+
error: z.string().optional(),
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export async function POST(request: Request): Promise<NextResponse> {
|
|
22
|
+
return protectedApi({
|
|
23
|
+
request,
|
|
24
|
+
schema: Schema,
|
|
25
|
+
authorization: () => {},
|
|
26
|
+
activity: handler,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function handler(
|
|
31
|
+
data: (typeof Schema)["input"]["_type"]
|
|
32
|
+
): Promise<NextResponse<(typeof Schema)["output"]["_type"]>> {
|
|
33
|
+
const user = (await getUserBySession(data.session)) as User;
|
|
34
|
+
let userData: Database["public"]["Tables"]["profiles"]["Update"];
|
|
35
|
+
// Find user's entry
|
|
36
|
+
{
|
|
37
|
+
let { data: queryUserData, error } = await supabase
|
|
38
|
+
.from("profiles")
|
|
39
|
+
.select("*")
|
|
40
|
+
.eq("uid", user.id);
|
|
41
|
+
|
|
42
|
+
if (!queryUserData?.length) {
|
|
43
|
+
return NextResponse.json(
|
|
44
|
+
{
|
|
45
|
+
error: "User cannot be retrieved from session",
|
|
46
|
+
},
|
|
47
|
+
{ status: 404 }
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
userData = queryUserData[0];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await supabase.from("passkeys").upsert({
|
|
54
|
+
id: userData.id!,
|
|
55
|
+
email: user.email!,
|
|
56
|
+
passkey: md5(data.data.passkey),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return NextResponse.json({});
|
|
60
|
+
}
|
package/api/submitScore.ts
CHANGED
|
@@ -2,6 +2,10 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { decryptString } from "../utils/security";
|
|
6
|
+
import { isEqual } from "lodash";
|
|
7
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
8
|
+
import { User } from "@supabase/supabase-js";
|
|
5
9
|
|
|
6
10
|
export const Schema = {
|
|
7
11
|
input: z.strictObject({
|
|
@@ -50,13 +54,27 @@ export async function handler({
|
|
|
50
54
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
51
55
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
52
56
|
> {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
const tokenContents = JSON.parse(decryptString(data.token));
|
|
58
|
+
if (
|
|
59
|
+
!isEqual(tokenContents, {
|
|
60
|
+
relayHwid: data.relayHwid,
|
|
61
|
+
songId: data.songId,
|
|
62
|
+
misses: data.misses,
|
|
63
|
+
hits: data.hits,
|
|
64
|
+
mapHash: data.mapHash,
|
|
65
|
+
mapNoteCount: data.mapNoteCount,
|
|
66
|
+
speed: data.speed,
|
|
67
|
+
})
|
|
68
|
+
) {
|
|
69
|
+
return NextResponse.json(
|
|
70
|
+
{
|
|
71
|
+
error: "Token miscalculation",
|
|
72
|
+
},
|
|
73
|
+
{ status: 500 }
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const user = (await getUserBySession(session)) as User;
|
|
60
78
|
|
|
61
79
|
let { data: userData, error: userError } = await supabase
|
|
62
80
|
.from("profiles")
|
package/api/updateBeatmapPage.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { NextResponse } from "next/server";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import { protectedApi, validUser } from "../utils/requestUtils";
|
|
4
4
|
import { supabase } from "../utils/supabase";
|
|
5
|
+
import { getUserBySession } from "../utils/getUserBySession";
|
|
6
|
+
import { User } from "@supabase/supabase-js";
|
|
5
7
|
|
|
6
8
|
export const Schema = {
|
|
7
9
|
input: z.strictObject({
|
|
@@ -34,7 +36,7 @@ export async function handler({
|
|
|
34
36
|
}: (typeof Schema)["input"]["_type"]): Promise<
|
|
35
37
|
NextResponse<(typeof Schema)["output"]["_type"]>
|
|
36
38
|
> {
|
|
37
|
-
const user = (await
|
|
39
|
+
const user = (await getUserBySession(session)) as User;
|
|
38
40
|
let { data: userData, error: userError } = await supabase
|
|
39
41
|
.from("profiles")
|
|
40
42
|
.select("*")
|
package/index.ts
CHANGED
|
@@ -353,6 +353,26 @@ import { Schema as GetMapUploadUrl } from "./api/getMapUploadUrl"
|
|
|
353
353
|
export { Schema as SchemaGetMapUploadUrl } from "./api/getMapUploadUrl"
|
|
354
354
|
export const getMapUploadUrl = handleApi({url:"/api/getMapUploadUrl",...GetMapUploadUrl})
|
|
355
355
|
|
|
356
|
+
// ./api/getPassToken.ts API
|
|
357
|
+
|
|
358
|
+
/*
|
|
359
|
+
export const Schema = {
|
|
360
|
+
input: z.strictObject({
|
|
361
|
+
data: z.object({
|
|
362
|
+
email: z.string(),
|
|
363
|
+
passkey: z.string(),
|
|
364
|
+
computerName: z.string(),
|
|
365
|
+
}),
|
|
366
|
+
}),
|
|
367
|
+
output: z.object({
|
|
368
|
+
token: z.string().optional(),
|
|
369
|
+
error: z.string().optional(),
|
|
370
|
+
}),
|
|
371
|
+
};*/
|
|
372
|
+
import { Schema as GetPassToken } from "./api/getPassToken"
|
|
373
|
+
export { Schema as SchemaGetPassToken } from "./api/getPassToken"
|
|
374
|
+
export const getPassToken = handleApi({url:"/api/getPassToken",...GetPassToken})
|
|
375
|
+
|
|
356
376
|
// ./api/getProfile.ts API
|
|
357
377
|
|
|
358
378
|
/*
|
|
@@ -562,6 +582,24 @@ import { Schema as SearchUsers } from "./api/searchUsers"
|
|
|
562
582
|
export { Schema as SchemaSearchUsers } from "./api/searchUsers"
|
|
563
583
|
export const searchUsers = handleApi({url:"/api/searchUsers",...SearchUsers})
|
|
564
584
|
|
|
585
|
+
// ./api/setPasskey.ts API
|
|
586
|
+
|
|
587
|
+
/*
|
|
588
|
+
export const Schema = {
|
|
589
|
+
input: z.strictObject({
|
|
590
|
+
session: z.string(),
|
|
591
|
+
data: z.object({
|
|
592
|
+
passkey: z.string(),
|
|
593
|
+
}),
|
|
594
|
+
}),
|
|
595
|
+
output: z.object({
|
|
596
|
+
error: z.string().optional(),
|
|
597
|
+
}),
|
|
598
|
+
};*/
|
|
599
|
+
import { Schema as SetPasskey } from "./api/setPasskey"
|
|
600
|
+
export { Schema as SchemaSetPasskey } from "./api/setPasskey"
|
|
601
|
+
export const setPasskey = handleApi({url:"/api/setPasskey",...SetPasskey})
|
|
602
|
+
|
|
565
603
|
// ./api/submitScore.ts API
|
|
566
604
|
|
|
567
605
|
/*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rhythia-api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "152.0.0",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"update": "bun ./scripts/update.ts",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"@aws-sdk/client-s3": "^3.637.0",
|
|
17
17
|
"@aws-sdk/s3-request-presigner": "^3.637.0",
|
|
18
18
|
"@netlify/zip-it-and-ship-it": "^9.37.9",
|
|
19
|
+
"@noble/ciphers": "^1.0.0",
|
|
19
20
|
"@supabase/supabase-js": "^2.45.1",
|
|
20
21
|
"@types/aws-lambda": "^8.10.143",
|
|
21
22
|
"@types/bun": "^1.1.6",
|
package/types/database.ts
CHANGED
|
@@ -147,6 +147,32 @@ export type Database = {
|
|
|
147
147
|
}
|
|
148
148
|
Relationships: []
|
|
149
149
|
}
|
|
150
|
+
passkeys: {
|
|
151
|
+
Row: {
|
|
152
|
+
email: string
|
|
153
|
+
id: number
|
|
154
|
+
passkey: string
|
|
155
|
+
}
|
|
156
|
+
Insert: {
|
|
157
|
+
email: string
|
|
158
|
+
id: number
|
|
159
|
+
passkey: string
|
|
160
|
+
}
|
|
161
|
+
Update: {
|
|
162
|
+
email?: string
|
|
163
|
+
id?: number
|
|
164
|
+
passkey?: string
|
|
165
|
+
}
|
|
166
|
+
Relationships: [
|
|
167
|
+
{
|
|
168
|
+
foreignKeyName: "passkeys_id_fkey"
|
|
169
|
+
columns: ["id"]
|
|
170
|
+
isOneToOne: true
|
|
171
|
+
referencedRelation: "profiles"
|
|
172
|
+
referencedColumns: ["id"]
|
|
173
|
+
},
|
|
174
|
+
]
|
|
175
|
+
}
|
|
150
176
|
profiles: {
|
|
151
177
|
Row: {
|
|
152
178
|
about_me: string | null
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { User } from "@supabase/supabase-js";
|
|
2
|
+
import { decryptString } from "./security";
|
|
3
|
+
import { supabase } from "./supabase";
|
|
4
|
+
|
|
5
|
+
export async function getUserBySession(session: string): Promise<User | null> {
|
|
6
|
+
const user = (await supabase.auth.getUser(session)).data.user;
|
|
7
|
+
|
|
8
|
+
if (user) {
|
|
9
|
+
return user;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const decryptedToken = JSON.parse(decryptString(session)) as {
|
|
14
|
+
userId: number;
|
|
15
|
+
email: string;
|
|
16
|
+
passKey: string;
|
|
17
|
+
computerName: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
let { data: queryPasskey, error } = await supabase
|
|
21
|
+
.from("passkeys")
|
|
22
|
+
.select("*,profiles(uid)")
|
|
23
|
+
.eq("id", decryptedToken.userId || "nil")
|
|
24
|
+
.eq("email", decryptedToken.email || "nil")
|
|
25
|
+
.eq("passkey", decryptedToken.passKey || "nil")
|
|
26
|
+
.single();
|
|
27
|
+
|
|
28
|
+
if (!queryPasskey) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (await supabase.auth.admin.getUserById(queryPasskey.profiles?.uid!))
|
|
33
|
+
.data.user;
|
|
34
|
+
} catch (error) {}
|
|
35
|
+
|
|
36
|
+
return null;
|
|
37
|
+
}
|
package/utils/requestUtils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
-
import { supabase } from "./supabase";
|
|
3
2
|
import { ZodObject } from "zod";
|
|
3
|
+
import { getUserBySession } from "./getUserBySession";
|
|
4
4
|
|
|
5
5
|
interface Props<
|
|
6
6
|
K = (...args: any[]) => Promise<NextResponse<any>>,
|
|
@@ -43,8 +43,8 @@ export async function validUser(data) {
|
|
|
43
43
|
);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const user = await
|
|
47
|
-
if (
|
|
46
|
+
const user = await getUserBySession(data.session);
|
|
47
|
+
if (!user) {
|
|
48
48
|
return NextResponse.json(
|
|
49
49
|
{
|
|
50
50
|
error: "Invalid user session",
|
|
@@ -53,15 +53,3 @@ export async function validUser(data) {
|
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
export async function getUser(data) {
|
|
58
|
-
if (!data.session) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const user = await supabase.auth.getUser(data.session);
|
|
63
|
-
if (user.error || !user.data.user) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
return user;
|
|
67
|
-
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { xchacha20poly1305 } from "@noble/ciphers/chacha";
|
|
2
|
+
import { managedNonce } from "@noble/ciphers/webcrypto";
|
|
3
|
+
import {
|
|
4
|
+
bytesToHex,
|
|
5
|
+
bytesToUtf8,
|
|
6
|
+
hexToBytes,
|
|
7
|
+
utf8ToBytes,
|
|
8
|
+
} from "@noble/ciphers/utils";
|
|
9
|
+
const key = hexToBytes(process.env.TOKEN_SECRET || "");
|
|
10
|
+
const chacha = managedNonce(xchacha20poly1305)(key); // manages nonces for you
|
|
11
|
+
|
|
12
|
+
export function encryptString(str: string) {
|
|
13
|
+
const data = utf8ToBytes(str);
|
|
14
|
+
return bytesToHex(chacha.encrypt(data));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function decryptString(str: string) {
|
|
18
|
+
const data = hexToBytes(str);
|
|
19
|
+
return bytesToUtf8(chacha.decrypt(data));
|
|
20
|
+
}
|
package/utils/star-calc/index.ts
CHANGED
|
@@ -48,7 +48,6 @@ export function rate(
|
|
|
48
48
|
) {
|
|
49
49
|
notes = notes.sort((a, b) => a.time - b.time);
|
|
50
50
|
const decoder = new BeatmapDecoder();
|
|
51
|
-
const encoder = new BeatmapEncoder();
|
|
52
51
|
const beatmap1 = decoder.decodeFromString(sampleMap);
|
|
53
52
|
let i = 0;
|
|
54
53
|
while (i < notes.length - 1) {
|
|
@@ -70,7 +69,6 @@ export function rate(
|
|
|
70
69
|
const mods = ruleset.createModCombination("RX");
|
|
71
70
|
const difficultyCalculator = ruleset.createDifficultyCalculator(beatmap1);
|
|
72
71
|
const difficultyAttributes = difficultyCalculator.calculateWithMods(mods);
|
|
73
|
-
encoder.encodeToPath("./map.osu", beatmap1);
|
|
74
72
|
return difficultyAttributes.starRating;
|
|
75
73
|
}
|
|
76
74
|
|