Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
its-felix committed Jan 8, 2024
1 parent 9eb1677 commit 8f7a6bb
Show file tree
Hide file tree
Showing 10 changed files with 390 additions and 10 deletions.
4 changes: 4 additions & 0 deletions src/components/breadcrumb/breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ const ROUTES = [{
path: 'legal',
text: 'Legal',
},
{
path: 'privacy-policy',
text: 'Privacy Policy',
},
// endregion
],
}] satisfies ReadonlyArray<RouteElement>;
Expand Down
20 changes: 20 additions & 0 deletions src/components/contact/contact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Box, Link } from '@cloudscape-design/components';
import React from 'react';
import { Copy } from '../common/copy';
import { KeyValuePairs, ValueWithLabel } from '../common/key-value-pairs';

export function Contact() {
return (
<KeyValuePairs columns={3}>
<ValueWithLabel label={'Ingame'}>
<Copy copyText={'Felix.9127'}>Felix.9127</Copy>
</ValueWithLabel>
<ValueWithLabel label={'Discord'}>
<Box>Join the <Link href={'https://discord.gg/9BpnA7sh'} external={true}>GW2 Development Community</Link> in channel <Box variant={'strong'}>#gw2auth</Box></Box>
</ValueWithLabel>
<ValueWithLabel label={'E-Mail'}>
<Box>Send us an E-Mail at <Copy copyText={'[email protected]'}><Link href={'mailto:[email protected]'} external={true}>[email protected]</Link></Copy></Box>
</ValueWithLabel>
</KeyValuePairs>
);
}
2 changes: 1 addition & 1 deletion src/components/cookie-preferences/cookie-preferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default function CookiePreferences({ onDismiss, ...modalProps }: ModalPro
}
}
></Category>
<Box variant={'small'}>Learn more about the cookies and local storage we use by reading our <RouterLink to={'/privacy-policy'}>Privacy Policy</RouterLink>.</Box>
<Box variant={'small'}>Learn more about the cookies and local storage we use by reading our <RouterLink to={'/privacy-policy'} fontSize={'inherit'}>Privacy Policy</RouterLink>.</Box>
</ColumnLayout>
</Modal>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/footer/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function Gw2AuthFooter(props: Gw2AuthFooterProps) {
<SpaceBetween size={'xs'} direction={'vertical'}>
<SpaceBetween size={isMobile ? 'xs' : 'm'} direction={isMobile ? 'vertical' : 'horizontal'}>
<RouterLink to={'/legal'}>{i18n.footer.legal}</RouterLink>
<RouterLink to={'/login'}>{i18n.footer.privacyPolicy}</RouterLink>
<RouterLink to={'/privacy-policy'}>{i18n.footer.privacyPolicy}</RouterLink>
<Link href={'https://github.com/gw2auth/oauth2-server/wiki/FAQ'} external={true}>{i18n.footer.faq}</Link>
<Link href={'https://github.com/gw2auth/oauth2-server/wiki'} external={true}>{i18n.footer.developerWiki}</Link>
<Link variant={'secondary'} href={'#'} onFollow={props.onCookiePreferencesClick}>{i18n.footer.cookiePreferences}</Link>
Expand Down
9 changes: 9 additions & 0 deletions src/lib/api/api.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ export interface ApiErrorBody {
message: string;
}

export interface ApplicationSummary {
accounts: number;
gw2ApiTokens: number;
verifiedGw2Accounts: number;
applications: number;
applicationClients: number;
applicationClientAccounts: number;
}

export enum Issuer {
GITHUB = 'github',
GOOGLE = 'google',
Expand Down
6 changes: 5 additions & 1 deletion src/lib/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
OAuth2TokenResponse,
PagedResponse,
VerificationStart,
VerificationSubmit, VerificationPendingChallenge, VerificationStartedChallenge, Account,
VerificationSubmit, VerificationPendingChallenge, VerificationStartedChallenge, Account, ApplicationSummary,
} from './api.model';

const KindSuccess = 0;
Expand Down Expand Up @@ -60,6 +60,10 @@ export type ApiResponse<T> = SuccessResponse<T> | ApiErrorResponse<T> | ErrorRes
export class ApiClient {
constructor(private readonly httpClient: HTTPClient) {}

getApplicationSummary(): Promise<ApiResponse<ApplicationSummary>> {
return transform(this.httpClient.fetch('/api-v2/application/summary'));
}

getAuthInfo(): Promise<ApiResponse<AuthInfo>> {
return transform(this.httpClient.fetch('/api-v2/authinfo'));
}
Expand Down
92 changes: 89 additions & 3 deletions src/pages/home.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,97 @@
import { Container, ContentLayout, Header } from '@cloudscape-design/components';
import React from 'react';
import {
Box,
Container, ContentLayout, Header, Link, Spinner,
} from '@cloudscape-design/components';
import React, { useEffect, useState } from 'react';
import { KeyValuePairs, ValueWithLabel } from '../components/common/key-value-pairs';
import { RouterLink } from '../components/common/router-link';
import { Contact } from '../components/contact/contact';
import { useAuthInfo } from '../components/util/context/auth-info';
import { useHttpClient } from '../components/util/context/http-client';
import { expectSuccess } from '../lib/api/api';
import { ApplicationSummary } from '../lib/api/api.model';

export default function Home() {
const { apiClient } = useHttpClient();
const [authInfo] = useAuthInfo();

const [summary, setSummary] = useState<ApplicationSummary>();

useEffect(() => {
(async () => {
const { body } = expectSuccess(await apiClient.getApplicationSummary());
setSummary(body);
})()
.finally(() => {});
}, [apiClient]);

return (
<ContentLayout header={<Header variant={'h1'}>Welcome to GW2Auth!</Header>}>
<Container>
<Container variant={'stacked'} header={<Header variant={'h2'}>As a user ...</Header>}>
<Box variant={'h5'}>Your portal to manage access shared with applications using the Guild Wars 2 API</Box>
<Box variant={'p'}>One API Token to rule them all.</Box>
<Box variant={'p'}>
We have observed that many users tend to create only a single API Token and pass this to every application out there.
This is convenient, since you only have to keep this single API Token and don't need to login to the Guild Wars 2 website everytime you want to use a new application.
</Box>
<Box variant={'p'}>
Even though this is convenient, this leads to a mess where you never know which applications keep reading your Guild Wars 2 data.
An API Token is valid until it is deleted - if only a single API Token is used for every application, you have no way to revoke the access only for a single application.
</Box>
<Box variant={'p'}>
GW2Auth allows you to add only a single API Token for each of your Guild Wars 2 accounts and manages each applications access for you.
You can revoke the access of a single application at any point in time through GW2Auth.
</Box>
<Box margin={{ top: 's' }} variant={'small'}>
GW2Auth uses <Link href={'https://wiki.guildwars2.com/wiki/API:2/createsubtoken'} external={true} fontSize={'inherit'}>subtokens</Link> to restrict the permissions granted to an application.
</Box>
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>As a developer ...</Header>}>
<Box variant={'h5'}>Multiple accounts? Account verification? Simple login? GW2Auth has your back</Box>
<Box variant={'p'}>
Creating an application that consumes API Tokens is easy at first, but as your application evolves, you might want to support more than that.
GW2Auth supports multiple Guild Wars 2 Accounts for a single user out of the box.
It also provides you with a unique user ID which can be used to create a unique user account on your side to enrich it with more data like personalized settings etc.
</Box>
<Box variant={'p'}>
You may also request to read the verification status of a users Guild Wars 2 Accounts to ensure a user is the legitimate owner of a Guild Wars 2 Account.
</Box>
<Box margin={{ top: 's', bottom: 'm' }} variant={'small'}>
Check out the <Link href={'https://github.com/gw2auth/oauth2-server/wiki/GW2Auth-Developer-Guide'} external={true} fontSize={'inherit'}>Developer Wiki</Link> to learn more.
</Box>

<Box variant={'h5'}>Get started now!</Box>
<Box variant={'p'}>
{authInfo
? (<Box>Create your first application on the <RouterLink to={'/dev/applications'}>Developer Page</RouterLink> and get started right away.</Box>)
: (<Box>Login or create an account and create your first application.</Box>)
}
</Box>
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>Many users trust GW2Auth</Header>}>
<KeyValuePairs columns={3}>
<LoadableValueWithLabel label={'Accounts'}>{summary?.accounts}</LoadableValueWithLabel>
<LoadableValueWithLabel label={'API Tokens'}>{summary?.gw2ApiTokens}</LoadableValueWithLabel>
<LoadableValueWithLabel label={'Verified GW2 Accounts'}>{summary?.verifiedGw2Accounts}</LoadableValueWithLabel>
<LoadableValueWithLabel label={'Applications'}>{summary?.applications}</LoadableValueWithLabel>
<LoadableValueWithLabel label={'Clients'}>{summary?.applicationClients}</LoadableValueWithLabel>
<LoadableValueWithLabel label={'Authorizations'}>{summary?.applicationClientAccounts}</LoadableValueWithLabel>
</KeyValuePairs>
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>Contact us</Header>}>
<Contact />
</Container>
</ContentLayout>
);
}

function LoadableValueWithLabel({ label, children }: React.PropsWithChildren<{ label: string }>) {
return (
<ValueWithLabel label={label}>
{children === undefined ? <Spinner /> : children}
</ValueWithLabel>
);
}
5 changes: 5 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Home from './home';
import Legal from './legal';
import { Login } from './login';
import { OAuth2Consent } from './oauth2-consent';
import { PrivacyPolicy } from './privacy-policy';

// region router
const router = createBrowserRouter([
Expand All @@ -44,6 +45,10 @@ const router = createBrowserRouter([
path: 'legal',
element: <Legal />,
},
{
path: 'privacy-policy',
element: <PrivacyPolicy />,
},
{
path: '',
element: (
Expand Down
34 changes: 30 additions & 4 deletions src/pages/legal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
import {
Box, ColumnLayout,
Container, ContentLayout, Header,
} from '@cloudscape-design/components';
import React from 'react';
import { Contact } from '../components/contact/contact';
import { useI18n } from '../components/util/context/i18n';

const LAST_UPDATED = new Date('2023-10-28');
const LAST_UPDATED = new Date('2024-01-08');

export default function Legal() {
const i18n = useI18n();

return (
<ContentLayout header={<Header variant={'h1'}>Legal Notice</Header>}>
<Container>
<Header>{i18n.legal.lastUpdated(LAST_UPDATED)}</Header>
<ContentLayout header={<Header variant={'h1'} description={i18n.legal.lastUpdated(LAST_UPDATED)}>Privacy Policy</Header>}>
<Container variant={'stacked'}>
<ColumnLayout columns={1}>
{...i18n.footer.copyrightGw2.map((v) => <Box variant={'strong'}>{v}</Box>)}
</ColumnLayout>
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>Contact</Header>}>
<Contact />
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>Liability for content</Header>}>
<Box variant={'p'}>
We make every effort to keep the information on our site current, but accept no liability whatsoever for the content provided.
Pursuant to §7 par. 1 of TMG (German Tele-Media Act), the law limits our responsibility as a service provider to our own content on these web pages.
According to §8 to §10 of TMG, we are not obligated to monitor third party information provided or stored on our website or to investigate circumstances that indicate illegal activity.
Obligations to remove or block the use of information under general law remain unaffected.
However, liability in this regard is only possible from the moment of knowledge of a specific infringement.
Upon notification of appropriate violations, we will remove this content immediately.
</Box>
</Container>

<Container variant={'stacked'} header={<Header variant={'h2'}>Copyright</Header>}>
<Box variant={'p'}>
The content and works provided on these webpages are governed by the copyright laws of Germany.
Duplication, processing, distribution, or any form of commercialisation of such material beyond the scope of the copyright law shall require the prior written consent of its respective author or creator.
</Box>
</Container>
</ContentLayout>
);
Expand Down
Loading

0 comments on commit 8f7a6bb

Please sign in to comment.