Skip to content

Commit

Permalink
[refactor] simplify Page Authorization based on MobX RESTful persistence
Browse files Browse the repository at this point in the history
[remove] Strapi session API
  • Loading branch information
TechQuery committed Sep 7, 2024
1 parent 84b5f8c commit 5754bf4
Show file tree
Hide file tree
Showing 16 changed files with 83 additions and 106 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
- tag: a
text: ${{ github.ref }}
href: ${{ github.server_url }}/${{ github.repository }}/tree/${{ github.ref_name }}
- - tag: text
text: 提交作者:
- tag: a
text: ${{ github.actor }}
href: ${{ github.server_url }}/${{ github.actor }}
- - tag: text
text: 预览链接:
- tag: a
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ jobs:
- tag: a
text: ${{ github.ref }}
href: ${{ github.server_url }}/${{ github.repository }}/tree/${{ github.ref_name }}
- - tag: text
text: 提交作者:
- tag: a
text: ${{ github.actor }}
href: ${{ github.server_url }}/${{ github.actor }}
- - tag: text
text: 预览链接:
- tag: a
Expand Down
18 changes: 6 additions & 12 deletions components/PlatformAdmin/PlatformAdminFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ import {
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Loading } from 'idea-react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { Component, Fragment, PropsWithChildren } from 'react';
import { Container, Nav } from 'react-bootstrap';

import { adminMenus } from '../../configuration/menu';
import { i18n } from '../../models/Base/Translation';
import platformAdminStore from '../../models/User/PlatformAdmin';
import sessionStore from '../../models/User/Session';
import { findDeep } from '../../utils/data';
import { MainBreadcrumb } from '../layout/MainBreadcrumb';
import { PageHead } from '../layout/PageHead';
Expand Down Expand Up @@ -49,13 +48,8 @@ export type PlatformAdminFrameProps = PropsWithChildren<{

@observer
export class PlatformAdminFrame extends Component<PlatformAdminFrameProps> {
@observable
accessor loading = false;

async componentDidMount() {
this.loading = true;
await platformAdminStore.checkAuthorization();
this.loading = false;
componentDidMount() {
sessionStore.getProfile();
}

get currentRoute() {
Expand Down Expand Up @@ -106,9 +100,9 @@ export class PlatformAdminFrame extends Component<PlatformAdminFrameProps> {
}

render() {
const { currentRoute, loading } = this,
const { currentRoute } = this,
{ children, title } = this.props,
{ isPlatformAdmin } = platformAdminStore;
{ downloading, isPlatformAdmin } = sessionStore;

return (
<div
Expand All @@ -117,7 +111,7 @@ export class PlatformAdminFrame extends Component<PlatformAdminFrameProps> {
>
<PageHead title={`${title} - ${t('platform_management')}`} />

{loading ? (
{downloading > 0 ? (
<Loading />
) : isPlatformAdmin ? (
<>
Expand Down
4 changes: 2 additions & 2 deletions components/Team/TeamManageFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { StaffType, TeamMemberRole } from '@kaiyuanshe/openhackathon-service';
import { Loading } from 'idea-react';
import { HTTPError } from 'koajax';
import { computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import { JWTProps, RouteProps } from 'next-ssr-middleware';
Expand All @@ -16,7 +17,6 @@ import { Col, Nav } from 'react-bootstrap';

import { activityTeamMenus } from '../../configuration/menu';
import activityStore from '../../models/Activity';
import { ErrorBaseData } from '../../models/Base';
import { i18n } from '../../models/Base/Translation';
import sessionStore from '../../models/User/Session';
import { findDeep } from '../../utils/data';
Expand Down Expand Up @@ -59,7 +59,7 @@ export class TeamManageFrame extends PureComponent<TeamManageFrameProps> {
? currentUserInThisTeam.role
: undefined;
} catch (error: any) {
const { status } = error as ErrorBaseData;
const { status } = (error as HTTPError).response;

if (status !== 404) this.teamMemberRole = undefined;
} finally {
Expand Down
16 changes: 13 additions & 3 deletions models/Activity/Team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import {
TeamWorkFilter,
} from '@kaiyuanshe/openhackathon-service';
import { action, computed, observable } from 'mobx';
import { ListModel, Stream, toggle } from 'mobx-restful';
import { ListModel, persist, restore, Stream, toggle } from 'mobx-restful';
import { buildURLData } from 'web-utility';

import { createListStream, Filter, InputData, TableModel } from '../Base';
import { WorkspaceModel } from '../Git';
import sessionStore from '../User/Session';
import sessionStore, { isServer } from '../User/Session';
import { AwardAssignment } from './Award';

export type TeamFilter = Filter<Team> & BaseFilter;
Expand Down Expand Up @@ -110,8 +110,18 @@ export class TeamMemberModel extends TableModel<TeamMember, MemberFilter> {
this.baseURI = `${baseURI}/member`;
}

restored = !isServer() && restore(this, 'TeamMember');

@persist()
@observable
accessor sessionOne: TeamMember | undefined;
accessor currentOne = {} as TeamMember;

@toggle('downloading')
async getOne(id: number) {
await this.restored;

return this.currentOne.id === id ? this.currentOne : super.getOne(id);
}

@toggle('uploading')
async joinTeam(data: JoinTeamReqBody) {
Expand Down
13 changes: 12 additions & 1 deletion models/Activity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import {
Questionnaire,
} from '@kaiyuanshe/openhackathon-service';
import { action, observable } from 'mobx';
import { toggle } from 'mobx-restful';
import { persist, restore, toggle } from 'mobx-restful';
import { buildURLData } from 'web-utility';

import { createListStream, Filter, InputData, TableModel } from '../Base';
import { GitModel } from '../Git';
import platformAdmin from '../User/PlatformAdmin';
import { isServer } from '../User/Session';
import { AwardModel } from './Award';
import { EnrollmentModel } from './Enrollment';
import { LogModel } from './Log';
Expand All @@ -37,6 +38,12 @@ export class ActivityModel extends TableModel<Hackathon, ActivityFilter> {
baseURI = 'hackathon';
indexKey = 'name' as const;

restored = !isServer() && restore(this, 'Activity');

@persist()
@observable
accessor currentOne = {} as Hackathon;

currentStaff?: StaffModel;
currentAward?: AwardModel;

Expand Down Expand Up @@ -114,6 +121,10 @@ export class ActivityModel extends TableModel<Hackathon, ActivityFilter> {
@action
@toggle('downloading')
async getOne(name: string) {
await this.restored;

if (this.currentOne.name === name) return this.currentOne;

const { detail, ...data } = await super.getOne(name);

this.staffOf(name);
Expand Down
7 changes: 2 additions & 5 deletions models/Base/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Base, ListChunk } from '@kaiyuanshe/openhackathon-service';
import { HTTPError } from 'koajax';
import { Filter as BaseFilter, ListModel, RESTClient } from 'mobx-restful';
import { buildURLData } from 'web-utility';

import sessionStore from '../User/Session';
import { ownClient } from '../User/Session';

export interface UploadUrl
extends Record<'filename' | 'uploadUrl' | 'url', string> {
Expand All @@ -30,8 +29,6 @@ export interface ListData<T> {
value: T[];
}

export const isServer = () => typeof window === 'undefined';

export async function* createListStream<T>(
path: string,
client: RESTClient,
Expand Down Expand Up @@ -60,7 +57,7 @@ export abstract class TableModel<
D extends Base,
F extends InputData<D> = InputData<D>,
> extends ListModel<D, F> {
client = sessionStore.client;
client = ownClient;

async loadPage(pageIndex: number, pageSize: number, filter: F) {
const { body } = await this.client.get<ListChunk<D>>(
Expand Down
64 changes: 25 additions & 39 deletions models/User/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,26 @@ import { Base, User } from '@kaiyuanshe/openhackathon-service';
import { HTTPClient } from 'koajax';
import { computed, observable } from 'mobx';
import { parseCookie, setCookie } from 'mobx-i18n';
import { BaseModel, toggle } from 'mobx-restful';
import { buildURLData, sleep } from 'web-utility';
import { BaseModel, persist, restore, toggle } from 'mobx-restful';
import { buildURLData } from 'web-utility';

import { AuthingUserBase } from '.';
export const isServer = () => typeof window === 'undefined';

const { localStorage, document } = globalThis;
const { token, JWT } = (globalThis.document ? parseCookie() : {}) as Record<
'token' | 'JWT',
string
>;

const { token } = (document ? parseCookie() : {}) as { token: string };

export const strapiClient = new HTTPClient({
baseURI: `${
process.env.NODE_ENV === 'development'
? 'http://127.0.0.1:1337'
: 'https://hackathon-server.kaiyuanshe.cn'
}/api/`,
export const ownClient = new HTTPClient({
baseURI: process.env.NEXT_PUBLIC_API_HOST,
responseType: 'json',
}).use(({ request }, next) => {
if (token)
request.headers = { ...request.headers, Authorization: `Bearer ${token}` };
if (JWT)
request.headers = { ...request.headers, Authorization: `Bearer ${JWT}` };

return next();
});

export const ownClient = new HTTPClient({
baseURI: process.env.NEXT_PUBLIC_API_HOST,
responseType: 'json',
});

export interface SessionUser
extends Base,
Record<'username' | 'email', string>,
Expand All @@ -39,36 +31,31 @@ export interface SessionUser
}

export class SessionModel extends BaseModel {
client = ownClient.use(({ request }, next) => {
const { token } = this.user || {};
client = ownClient;

if (token)
request.headers = {
...request.headers,
Authorization: `Bearer ${token}`,
};
return next();
});
restored = !isServer() && restore(this, 'Session');

@persist()
@observable
accessor user: User | undefined =
localStorage?.user && JSON.parse(localStorage.user);
accessor user: User | undefined;

@computed
get metaOAuth() {
const { token } = parseCookie(globalThis.document?.cookie || '');

return { github: { accessToken: token } };
}

@toggle('uploading')
async signIn(profile: AuthingUserBase, reload = false) {
const { body } = await this.client.post<User>('login', profile);
@computed
get isPlatformAdmin() {
return !!this.user?.roles.includes(0);
}

@toggle('downloading')
async getProfile() {
await this.restored;

setCookie('token', body!.token!, { path: '/' });
localStorage.user = JSON.stringify(body);
if (this.user) return this.user;

if (reload) sleep().then(() => location.reload());
const { body } = await this.client.get<User>('user/session');

return (this.user = body);
}
Expand All @@ -83,7 +70,6 @@ export class SessionModel extends BaseModel {
signOut(reload = false) {
setCookie('token', '', { path: '/', expires: new Date() });
setCookie('JWT', '', { path: '/', expires: new Date() });
localStorage?.clear();

this.user = undefined;

Expand Down
8 changes: 0 additions & 8 deletions models/User/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,6 @@ import { User, UserRankListChunk } from '@kaiyuanshe/openhackathon-service';

import { Filter, TableModel } from '../Base';

export interface AuthingUserBase {
_id?: string;
openid: string;
unionid?: string;
userId: string;
userPoolId: string;
}

export interface UserFilter extends Filter<User> {
keywords?: string;
}
Expand Down
2 changes: 1 addition & 1 deletion pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { FC } from 'react';
import { Col, Container, Image, Row } from 'react-bootstrap';

import { MainNavigation } from '../components/layout/MainNavigation';
import { ErrorBaseData, isServer } from '../models/Base';
import { i18n } from '../models/Base/Translation';
import { isServer } from '../models/User/Session';

configure({ enforceActions: 'never' });

Expand Down
3 changes: 1 addition & 2 deletions pages/activity/[name]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ import { TeamCard } from '../../../components/Team/TeamCard';
import { TeamCreateModal } from '../../../components/Team/TeamCreateModal';
import { TeamListLayout } from '../../../components/Team/TeamList';
import activityStore, { ActivityModel } from '../../../models/Activity';
import { isServer } from '../../../models/Base';
import { i18n } from '../../../models/Base/Translation';
import sessionStore from '../../../models/User/Session';
import sessionStore, { isServer } from '../../../models/User/Session';
import { convertDatetime } from '../../../utils/time';

const { t } = i18n;
Expand Down
2 changes: 1 addition & 1 deletion pages/activity/[name]/manage/questionnaire.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { QuestionnaireCreate } from '../../../../components/Activity/Questionnai
import { QuestionnaireForm } from '../../../../components/Activity/QuestionnairePreview';
import { QuestionnaireTable } from '../../../../components/Activity/QuestionnaireTable';
import activityStore from '../../../../models/Activity';
import { isServer } from '../../../../models/Base';
import { i18n } from '../../../../models/Base/Translation';
import { isServer } from '../../../../models/User/Session';
import { sessionGuard } from '../../../api/core';

const { t } = i18n;
Expand Down
6 changes: 3 additions & 3 deletions pages/activity/[name]/team/[tid]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TeamWork,
} from '@kaiyuanshe/openhackathon-service';
import { Icon } from 'idea-react';
import { HTTPError } from 'koajax';
import { computed, observable } from 'mobx';
import { observer } from 'mobx-react';
import { observePropsState } from 'mobx-react-helper';
Expand All @@ -21,9 +22,8 @@ import { JoinTeamModal } from '../../../../../components/Team/JoinTeamModal';
import { TeamMemberListLayout } from '../../../../../components/Team/TeamMemberList';
import { TeamWorkList } from '../../../../../components/Team/TeamWorkList';
import activityStore, { ActivityModel } from '../../../../../models/Activity';
import { ErrorBaseData, isServer } from '../../../../../models/Base';
import { i18n } from '../../../../../models/Base/Translation';
import sessionStore from '../../../../../models/User/Session';
import sessionStore, { isServer } from '../../../../../models/User/Session';

const { t } = i18n;

Expand Down Expand Up @@ -132,7 +132,7 @@ export default class TeamPage extends PureComponent<TeamPageProps> {
: undefined;
this.teamMemberRole = this.currentUserInThisTeam?.role || '';
} catch (error: any) {
const { status } = error as ErrorBaseData;
const { status } = (error as HTTPError).response;

if (status !== 404) this.teamMemberRole = '';
}
Expand Down
Loading

1 comment on commit 5754bf4

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for open-hackathon ready!

✅ Preview
https://open-hackathon-ozgn1n8rh-techquerys-projects.vercel.app

Built with commit 5754bf4.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.