mirror of
https://github.com/jorgev259/soc_site-astro.git
synced 2025-06-29 07:57:41 +00:00
This commit is contained in:
parent
0ec019f959
commit
4cafc41b88
11 changed files with 192 additions and 77 deletions
|
|
@ -21,7 +21,11 @@ export default defineConfig({
|
||||||
optional: true,
|
optional: true,
|
||||||
default: 'http://localhost:4321'
|
default: 'http://localhost:4321'
|
||||||
}),
|
}),
|
||||||
WEBHOOK_URL: envField.string({ context: 'server', access: 'secret' })
|
WEBHOOK_URL: envField.string({ context: 'server', access: 'secret' }),
|
||||||
|
DISCORD_OAUTH_ID: envField.string({ context: 'server', access: 'public' }),
|
||||||
|
DISCORD_OAUTH_SECRET: envField.string({ context: 'server', access: 'secret' }),
|
||||||
|
DISCORD_GUILD_ID: envField.string({ context: 'server', access: 'public' }),
|
||||||
|
DISCORD_DONATOR_ID: envField.string({ context: 'server', access: 'public' })
|
||||||
},
|
},
|
||||||
validateSecrets: true
|
validateSecrets: true
|
||||||
},
|
},
|
||||||
|
|
@ -53,6 +57,7 @@ export default defineConfig({
|
||||||
'/game/list': { status: 307, destination: '/maintenance' },
|
'/game/list': { status: 307, destination: '/maintenance' },
|
||||||
'/platform/list': { status: 307, destination: '/maintenance' },
|
'/platform/list': { status: 307, destination: '/maintenance' },
|
||||||
'/platform/[id]': { status: 307, destination: '/maintenance' },
|
'/platform/[id]': { status: 307, destination: '/maintenance' },
|
||||||
|
'/profile': { status: 307, destination: '/maintenance' },
|
||||||
'/profile/[username]': { status: 307, destination: '/maintenance' },
|
'/profile/[username]': { status: 307, destination: '/maintenance' },
|
||||||
'/series/[slug]': { status: 307, destination: '/maintenance' },
|
'/series/[slug]': { status: 307, destination: '/maintenance' },
|
||||||
'/series/list': { status: 307, destination: '/maintenance' },
|
'/series/list': { status: 307, destination: '/maintenance' },
|
||||||
|
|
|
||||||
144
messages/en.json
144
messages/en.json
|
|
@ -1,69 +1,77 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://inlang.com/schema/inlang-message-format",
|
"$schema": "https://inlang.com/schema/inlang-message-format",
|
||||||
"register": "Register",
|
"register": "Register",
|
||||||
"login": "Login",
|
"login": "Login",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"recoverPassword": "Recover Password",
|
"recoverPassword": "Recover Password",
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"lastaddednav": "Last Added",
|
"lastaddednav": "Last Added",
|
||||||
"albumlist": "Album List",
|
"albumlist": "Album List",
|
||||||
"games": "Games",
|
"games": "Games",
|
||||||
"albums": "Albums",
|
"albums": "Albums",
|
||||||
"series": "Series",
|
"series": "Series",
|
||||||
"publishers": "Publishers",
|
"publishers": "Publishers",
|
||||||
"platforms": "Platforms",
|
"platforms": "Platforms",
|
||||||
"gamelist": "Game List",
|
"gamelist": "Game List",
|
||||||
"animation": "Animation",
|
"animation": "Animation",
|
||||||
"animationlist": "Animation List",
|
"animationlist": "Animation List",
|
||||||
"studios": "Studios",
|
"studios": "Studios",
|
||||||
"requests": "Requests",
|
"requests": "Requests",
|
||||||
"submitalbum": "Submit Album",
|
"submitalbum": "Submit Album",
|
||||||
"adminGrounds": "Admin Grounds",
|
"adminGrounds": "Admin Grounds",
|
||||||
"manageAlbums": "Manage Albums",
|
"manageAlbums": "Manage Albums",
|
||||||
"manageUsers": "Manage Users",
|
"manageUsers": "Manage Users",
|
||||||
"manageRequests": "Manage Requests",
|
"manageRequests": "Manage Requests",
|
||||||
"manageSubmissions": "Manage Submissions",
|
"manageSubmissions": "Manage Submissions",
|
||||||
"profilePic": "Profile picture",
|
"profilePic": "Profile picture",
|
||||||
"emailSuccess": "An email with further instructions has been sent to the address linked to the account. Check your spam folder.",
|
"emailSuccess": "An email with further instructions has been sent to the address linked to the account. Check your spam folder.",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"newPassword": "New password",
|
"newPassword": "New password",
|
||||||
"newPasswordRetype": "Re-type new password",
|
"newPasswordRetype": "Re-type new password",
|
||||||
"savePassword": "Save Password",
|
"savePassword": "Save Password",
|
||||||
"passwordResetSuccesful": "Password reset succesfully",
|
"passwordResetSuccesful": "Password reset succesfully",
|
||||||
"displayName": "Display name",
|
"displayName": "Display name",
|
||||||
"lastAddedSidebar": "Last Added",
|
"lastAddedSidebar": "Last Added",
|
||||||
"getLucky": "Get Lucky",
|
"getLucky": "Get Lucky",
|
||||||
"randomPull": "Random Pull",
|
"randomPull": "Random Pull",
|
||||||
"highlightAlbum": "Highlight Soundtrack",
|
"highlightAlbum": "Highlight Soundtrack",
|
||||||
"ostCount": "Soundtrack Count",
|
"ostCount": "Soundtrack Count",
|
||||||
"recentReleases": "Recent Releases",
|
"recentReleases": "Recent Releases",
|
||||||
"moreGameReleases": "More Game Releases",
|
"moreGameReleases": "More Game Releases",
|
||||||
"moreAnimReleases": "more Animation releases",
|
"moreAnimReleases": "more Animation releases",
|
||||||
"moreLastAdded": "more Last Added",
|
"moreLastAdded": "more Last Added",
|
||||||
"lastAdded": "Last Added",
|
"lastAdded": "Last Added",
|
||||||
"releaseDate": "Release Date",
|
"releaseDate": "Release Date",
|
||||||
"artists": "Artists",
|
"artists": "Artists",
|
||||||
"classification": "Classification",
|
"classification": "Classification",
|
||||||
"AnimationOsts": "Animation Soundtracks",
|
"AnimationOsts": "Animation Soundtracks",
|
||||||
"GameOsts": "Game Soundtracks",
|
"GameOsts": "Game Soundtracks",
|
||||||
"publishedBy": "Published by",
|
"publishedBy": "Published by",
|
||||||
"animations": "Animations",
|
"animations": "Animations",
|
||||||
"avgRating": "Average Rating",
|
"avgRating": "Average Rating",
|
||||||
"tracklist": "Tracklist",
|
"tracklist": "Tracklist",
|
||||||
"donationCall": "Consider Donating to remove ads",
|
"donationCall": "Consider Donating to remove ads",
|
||||||
"donationSteps": "After donating, if the donation e-mail is the same as the one used in the notation, it should be\r\n available in a few hours. If not, contact us on",
|
"donationSteps": "After donating, if the donation e-mail is the same as the one used in the notation, it should be\r\n available in a few hours. If not, contact us on",
|
||||||
"brokenLinkContact": "Broken Link? Contact us at Join our Discord!",
|
"brokenLinkContact": "Broken Link? Contact us at Join our Discord!",
|
||||||
"mediafirePermission": "MediaFire permission denied?",
|
"mediafirePermission": "MediaFire permission denied?",
|
||||||
"mediafirePermissionGuide": "Check this guide",
|
"mediafirePermissionGuide": "Check this guide",
|
||||||
"disc": "Disc",
|
"disc": "Disc",
|
||||||
"checkVGMDB": "Check album at",
|
"checkVGMDB": "Check album at",
|
||||||
"buyOriginal": "Buy The Original Soundtrack to support the artists",
|
"buyOriginal": "Buy The Original Soundtrack to support the artists",
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"flyInc": "Fly.inc",
|
"flyInc": "Fly.inc",
|
||||||
"ouoIO": "ouo.io",
|
"ouoIO": "ouo.io",
|
||||||
"direct": "Direct",
|
"direct": "Direct",
|
||||||
"relatedAlbums": "Related Albums"
|
"relatedAlbums": "Related Albums",
|
||||||
}
|
"loginDiscord": "Login using Discord",
|
||||||
|
"profile": "Profile",
|
||||||
|
"linkDiscord": "Link Discord account",
|
||||||
|
"loggedInPage": "You need to be logged in to access this page",
|
||||||
|
"alreadyDonator": "You are already a donator!",
|
||||||
|
"discordNeeded": "You need to link your Discord account to access this page",
|
||||||
|
"discordRoleNeeded": "You need the Donator Discord role to access this page",
|
||||||
|
"addedDonator": "Added donator benefits to your account!"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `verification` MODIFY `value` TEXT NOT NULL;
|
||||||
|
|
@ -442,7 +442,7 @@ model session {
|
||||||
model verification {
|
model verification {
|
||||||
id String @id
|
id String @id
|
||||||
identifier String
|
identifier String
|
||||||
value String
|
value String @db.Text
|
||||||
expiresAt DateTime
|
expiresAt DateTime
|
||||||
createdAt DateTime
|
createdAt DateTime
|
||||||
updatedAt DateTime
|
updatedAt DateTime
|
||||||
|
|
|
||||||
14
src/auth.ts
14
src/auth.ts
|
|
@ -1,6 +1,7 @@
|
||||||
import { betterAuth } from 'better-auth'
|
import { betterAuth } from 'better-auth'
|
||||||
import { prismaAdapter } from 'better-auth/adapters/prisma'
|
import { prismaAdapter } from 'better-auth/adapters/prisma'
|
||||||
import { username, bearer } from 'better-auth/plugins'
|
import { username, bearer } from 'better-auth/plugins'
|
||||||
|
import { DISCORD_OAUTH_ID, DISCORD_OAUTH_SECRET } from 'astro:env/server'
|
||||||
|
|
||||||
import prismaClient from './utils/prisma-client'
|
import prismaClient from './utils/prisma-client'
|
||||||
import { sendEmail } from './utils/email'
|
import { sendEmail } from './utils/email'
|
||||||
|
|
@ -11,6 +12,19 @@ export const auth = betterAuth({
|
||||||
database: prismaAdapter(prismaClient, { provider: 'mysql' }),
|
database: prismaAdapter(prismaClient, { provider: 'mysql' }),
|
||||||
user: { modelName: 'users' },
|
user: { modelName: 'users' },
|
||||||
plugins: [username(), bearer()],
|
plugins: [username(), bearer()],
|
||||||
|
account: {
|
||||||
|
accountLinking: {
|
||||||
|
enabled: true,
|
||||||
|
allowDifferentEmails: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
socialProviders: {
|
||||||
|
discord: {
|
||||||
|
clientId: DISCORD_OAUTH_ID,
|
||||||
|
clientSecret: DISCORD_OAUTH_SECRET,
|
||||||
|
scope: ['identify', 'email', 'guilds.members.read']
|
||||||
|
}
|
||||||
|
},
|
||||||
emailVerification: {
|
emailVerification: {
|
||||||
sendOnSignUp: true,
|
sendOnSignUp: true,
|
||||||
autoSignInAfterVerification: true,
|
autoSignInAfterVerification: true,
|
||||||
|
|
|
||||||
|
|
@ -79,13 +79,20 @@ function LoginForm(props: { setForm: SetState<FormOptions>; setModalOpen: SetSta
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex'>
|
<div className='flex justify-center gap-x-2'>
|
||||||
<Button loading={loading} disabled={loading} className='mx-auto px-6'>
|
<Button loading={loading} disabled={loading} className='px-6' type='submit'>
|
||||||
{m.login()}
|
{m.login()}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={(ev) => {
|
||||||
|
ev.preventDefault()
|
||||||
|
signIn.social({ provider: 'discord', callbackURL: window.location.href })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{m.loginDiscord()}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className='mx-auto'>
|
<div className='mx-auto'>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,37 @@
|
||||||
---
|
---
|
||||||
|
import * as m from 'paraglide/messages'
|
||||||
|
import prismaClient from 'utils/prisma-client'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
import RegisterBtn from './RegisterButton'
|
import RegisterBtn from './RegisterButton'
|
||||||
import LoginBtn from './LoginButton'
|
import LoginBtn from './LoginButton'
|
||||||
import LogoutBtn from './LogoutButton'
|
import LogoutBtn from './LogoutButton'
|
||||||
|
import Button from 'components/Button'
|
||||||
|
|
||||||
const session = Astro.locals.session
|
const { permissions, session, user } = Astro.locals
|
||||||
|
const isDonator = permissions.includes('SKIP_ADS')
|
||||||
|
|
||||||
|
const discordAcc = user
|
||||||
|
? await prismaClient.account.findFirst({
|
||||||
|
where: { providerId: 'discord', userId: user.id }
|
||||||
|
})
|
||||||
|
: null
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class='px-2 flex gap-x-2 justify-end absolute w-full md:ms-auto md:block md:w-auto md:static'>
|
<div class='px-2 flex gap-x-2 justify-end absolute w-full md:ms-auto md:block md:w-auto md:static'>
|
||||||
{
|
{
|
||||||
session ? (
|
session ? (
|
||||||
<LogoutBtn client:only='react' />
|
<>
|
||||||
|
{!discordAcc ? (
|
||||||
|
<Button id='link-discord' className='rounded-t-none'>
|
||||||
|
{m.linkDiscord()}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
<a href='/profile'>
|
||||||
|
<Button className={clsx(['rounded-t-none', { '!bg-amber-400': isDonator }])}>{m.profile()}</Button>
|
||||||
|
</a>
|
||||||
|
<LogoutBtn client:only='react' />
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<LoginBtn client:only='react' />
|
<LoginBtn client:only='react' />
|
||||||
|
|
@ -18,3 +40,12 @@ const session = Astro.locals.session
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { linkSocial } from 'utils/auth-client'
|
||||||
|
|
||||||
|
const discordBtn = document.getElementById('link-discord')
|
||||||
|
discordBtn?.addEventListener('click', () => {
|
||||||
|
linkSocial({ provider: 'discord', callbackURL: window.location.href })
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
|
||||||
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
|
|
@ -6,5 +6,6 @@ declare namespace App {
|
||||||
session: import('better-auth').Session | null
|
session: import('better-auth').Session | null
|
||||||
permissions: string[]
|
permissions: string[]
|
||||||
pages: string[]
|
pages: string[]
|
||||||
|
roles: string[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
||||||
context.locals.session = isAuthed.session
|
context.locals.session = isAuthed.session
|
||||||
|
|
||||||
const user = await prismaClient.users.findUnique({
|
const user = await prismaClient.users.findUnique({
|
||||||
select: { roles: { select: { roles: { select: { permissions: true } } } } },
|
select: { roles: { select: { roleName: true, roles: { select: { permissions: true } } } } },
|
||||||
where: { id: isAuthed.user.id }
|
where: { id: isAuthed.user.id }
|
||||||
})
|
})
|
||||||
const permissions = (user?.roles.map((r) => r.roles.permissions).flat() as string[]) ?? []
|
const permissions = (user?.roles.map((r) => r.roles.permissions).flat() as string[]) ?? []
|
||||||
|
|
@ -22,6 +22,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
||||||
|
|
||||||
context.locals.permissions = permissions
|
context.locals.permissions = permissions
|
||||||
context.locals.pages = pages
|
context.locals.pages = pages
|
||||||
|
context.locals.roles = user?.roles.map((r) => r.roleName) ?? []
|
||||||
} else {
|
} else {
|
||||||
context.locals.user = null
|
context.locals.user = null
|
||||||
context.locals.session = null
|
context.locals.session = null
|
||||||
|
|
|
||||||
46
src/pages/donator/check.astro
Normal file
46
src/pages/donator/check.astro
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
import * as m from 'paraglide/messages'
|
||||||
|
import { DISCORD_DONATOR_ID } from 'astro:env/server'
|
||||||
|
import prismaClient from 'utils/prisma-client'
|
||||||
|
|
||||||
|
const { session, user, roles } = Astro.locals
|
||||||
|
|
||||||
|
async function getMessage() {
|
||||||
|
if (!user || !session) {
|
||||||
|
return m.loggedInPage()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roles.includes('Donator')) {
|
||||||
|
return m.alreadyDonator()
|
||||||
|
}
|
||||||
|
|
||||||
|
const discordAcc = await prismaClient.account.findFirst({
|
||||||
|
where: { providerId: 'discord', userId: session.userId }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!discordAcc) {
|
||||||
|
return m.discordNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberInfoRes = await fetch(`https://discord.com/api/users/@me/guilds/535484312124915714/member`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${discordAcc.accessToken}`,
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const memberInfo: { roles: string[] } = await memberInfoRes.json()
|
||||||
|
const isDiscordDonator = memberInfo.roles.includes(DISCORD_DONATOR_ID)
|
||||||
|
|
||||||
|
if (!isDiscordDonator) {
|
||||||
|
return m.discordRoleNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
await prismaClient.user_Role.create({ data: { userUsername: user.id, roleName: 'Donator' } })
|
||||||
|
return m.addedDonator()
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = await getMessage()
|
||||||
|
---
|
||||||
|
|
||||||
|
<div>{message}</div>
|
||||||
|
|
@ -4,4 +4,4 @@ import { usernameClient } from 'better-auth/client/plugins'
|
||||||
export const authClient = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
plugins: [usernameClient()]
|
plugins: [usernameClient()]
|
||||||
})
|
})
|
||||||
export const { useSession, signIn, signUp, signOut, forgetPassword, resetPassword } = authClient
|
export const { useSession, signIn, signUp, signOut, forgetPassword, resetPassword, linkSocial } = authClient
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue