Initial Typescript models.

This commit is contained in:
Brian Cao 2022-11-15 13:21:14 -08:00
parent 04e9f06e93
commit 0aaba8cbd1
74 changed files with 1144 additions and 768 deletions

View file

@ -10,8 +10,24 @@ import {
import { getUser } from 'queries';
import { secret } from 'lib/crypto';
import redis from 'lib/redis';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { User } from 'interface/api/models';
export default async (req, res) => {
export interface LoginRequestBody {
username: string;
password: string;
}
export interface LoginResponse {
token: string;
user: User;
}
export default async (
req: NextApiRequestQueryBody<any, LoginRequestBody>,
res: NextApiResponse<LoginResponse>,
) => {
if (req.method === 'POST') {
const { username, password } = req.body;
@ -19,7 +35,7 @@ export default async (req, res) => {
return badRequest(res);
}
const user = await getUser({ username });
const user = await getUser({ username }, true);
if (user && checkPassword(password, user.password)) {
if (redis.enabled) {

View file

@ -2,8 +2,9 @@ import { methodNotAllowed, ok } from 'next-basics';
import { useAuth } from 'lib/middleware';
import redis from 'lib/redis';
import { getAuthToken } from 'lib/auth';
import { NextApiRequest, NextApiResponse } from 'next';
export default async (req, res) => {
export default async (req: NextApiRequest, res: NextApiResponse) => {
await useAuth(req, res);
if (req.method === 'POST') {

View file

@ -1,8 +0,0 @@
import { useAuth } from 'lib/middleware';
import { ok } from 'next-basics';
export default async (req, res) => {
await useAuth(req, res);
return ok(res, req.auth);
};

10
pages/api/auth/verify.ts Normal file
View file

@ -0,0 +1,10 @@
import { NextApiRequestAuth } from 'interface/api/nextApi';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { ok } from 'next-basics';
export default async (req: NextApiRequestAuth, res: NextApiResponse) => {
await useAuth(req, res);
return ok(res, req.auth);
};

View file

@ -6,8 +6,23 @@ import { savePageView, saveEvent } from 'queries';
import { useCors, useSession } from 'lib/middleware';
import { getJsonBody, getIpAddress } from 'lib/request';
import { secret } from 'lib/crypto';
import { NextApiRequest, NextApiResponse } from 'next';
export default async (req, res) => {
export interface NextApiRequestCollect extends NextApiRequest {
session: {
id: string;
websiteId: string;
hostname: string;
browser: string;
os: string;
device: string;
screen: string;
language: string;
country: string;
};
}
export default async (req: NextApiRequestCollect, res: NextApiResponse) => {
await useCors(req, res);
if (isbot(req.headers['user-agent']) && !process.env.DISABLE_BOT_CHECK) {
@ -74,6 +89,7 @@ export default async (req, res) => {
await saveEvent({
...session,
url,
referrer,
eventName,
eventData,
});

View file

@ -1,6 +1,15 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { ok, methodNotAllowed } from 'next-basics';
export default async (req, res) => {
export interface ConfigResponse {
basePath: string;
trackerScriptName: string;
updatesDisabled: boolean;
telemetryDisabled: boolean;
adminDisabled: boolean;
}
export default async (req: NextApiRequest, res: NextApiResponse<ConfigResponse>) => {
if (req.method === 'GET') {
return ok(res, {
basePath: process.env.BASE_PATH || '',

View file

@ -1,5 +0,0 @@
import { ok } from 'next-basics';
export default async (req, res) => {
return ok(res);
};

6
pages/api/heartbeat.ts Normal file
View file

@ -0,0 +1,6 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { ok } from 'next-basics';
export default async (req: NextApiRequest, res: NextApiResponse) => {
return ok(res);
};

View file

@ -1,10 +1,13 @@
import { subMinutes } from 'date-fns';
import { ok, methodNotAllowed, createToken } from 'next-basics';
import { useAuth } from 'lib/middleware';
import { getUserWebsites, getRealtimeData } from 'queries';
import { RealtimeInit } from 'interface/api/models';
import { NextApiRequestAuth } from 'interface/api/nextApi';
import { secret } from 'lib/crypto';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { createToken, methodNotAllowed, ok } from 'next-basics';
import { getRealtimeData, getUserWebsites } from 'queries';
export default async (req, res) => {
export default async (req: NextApiRequestAuth, res: NextApiResponse<RealtimeInit>) => {
await useAuth(req, res);
if (req.method === 'GET') {

View file

@ -3,8 +3,18 @@ import { useAuth } from 'lib/middleware';
import { getRealtimeData } from 'queries';
import { SHARE_TOKEN_HEADER } from 'lib/constants';
import { secret } from 'lib/crypto';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { RealtimeUpdate } from 'interface/api/models';
export default async (req, res) => {
export interface InitUpdateRequestQuery {
start_at: string;
}
export default async (
req: NextApiRequestQueryBody<InitUpdateRequestQuery>,
res: NextApiResponse<RealtimeUpdate>,
) => {
await useAuth(req, res);
if (req.method === 'GET') {

View file

@ -1,8 +1,22 @@
import { getWebsite } from 'queries';
import { ok, notFound, methodNotAllowed, createToken } from 'next-basics';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { secret } from 'lib/crypto';
import { NextApiResponse } from 'next';
import { createToken, methodNotAllowed, notFound, ok } from 'next-basics';
import { getWebsite } from 'queries';
export default async (req, res) => {
export interface ShareRequestQuery {
id: string;
}
export interface ShareResponse {
id: string;
token: string;
}
export default async (
req: NextApiRequestQueryBody<ShareRequestQuery>,
res: NextApiResponse<ShareResponse>,
) => {
const { id: shareId } = req.query;
if (req.method === 'GET') {

View file

@ -1,8 +1,23 @@
import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getUser, deleteUser, updateUser } from 'queries';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { User } from 'interface/api/models';
export default async (req, res) => {
export interface UserReqeustQuery {
id: string;
}
export interface UserReqeustBody {
username: string;
password: string;
}
export default async (
req: NextApiRequestQueryBody<UserReqeustQuery, UserReqeustBody>,
res: NextApiResponse<User>,
) => {
await useAuth(req, res);
const {
@ -29,7 +44,7 @@ export default async (req, res) => {
const user = await getUser({ id });
const data = {};
const data: any = {};
if (password) {
data.password = hashPassword(password);

View file

@ -10,8 +10,23 @@ import {
} from 'next-basics';
import { allowQuery } from 'lib/auth';
import { TYPE_USER } from 'lib/constants';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { User } from 'interface/api/models';
export default async (req, res) => {
export interface UserPasswordRequestQuery {
id: string;
}
export interface UserPasswordRequestBody {
current_password: string;
new_password: string;
}
export default async (
req: NextApiRequestQueryBody<UserPasswordRequestQuery, UserPasswordRequestBody>,
res: NextApiResponse<User>,
) => {
await useAuth(req, res);
const { current_password, new_password } = req.body;

View file

@ -2,8 +2,20 @@ import { ok, unauthorized, methodNotAllowed, badRequest, hashPassword } from 'ne
import { useAuth } from 'lib/middleware';
import { uuid } from 'lib/crypto';
import { createUser, getUser, getUsers } from 'queries';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { User } from 'interface/api/models';
export default async (req, res) => {
export interface UsersRequestBody {
username: string;
password: string;
id: string;
}
export default async (
req: NextApiRequestQueryBody<UsersRequestBody>,
res: NextApiResponse<User[] | User>,
) => {
await useAuth(req, res);
const {

View file

@ -3,8 +3,18 @@ import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { getActiveVisitors } from 'queries';
import { TYPE_WEBSITE } from 'lib/constants';
import { WebsiteActive } from 'interface/api/models';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
export default async (req, res) => {
export interface WebsiteActiveRequestQuery {
id: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteActiveRequestQuery>,
res: NextApiResponse<WebsiteActive>,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -4,8 +4,27 @@ import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { TYPE_WEBSITE } from 'lib/constants';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { WebsiteMetric } from 'interface/api/models';
export default async (req, res) => {
export interface WebsiteEventDataRequestQuery {
id: string;
}
export interface WebsiteEventDataRequestBody {
start_at: string;
end_at: string;
timezone: string;
event_name: string;
columns: { [key: string]: 'count' | 'max' | 'min' | 'avg' | 'sum' };
filters?: { [key: string]: any };
}
export default async (
req: NextApiRequestQueryBody<WebsiteEventDataRequestQuery, WebsiteEventDataRequestBody>,
res: NextApiResponse<WebsiteMetric>,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -1,13 +1,29 @@
import moment from 'moment-timezone';
import { getEventMetrics } from 'queries';
import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
import { WebsiteMetric } from 'interface/api/models';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { TYPE_WEBSITE } from 'lib/constants';
import { useAuth, useCors } from 'lib/middleware';
import moment from 'moment-timezone';
import { NextApiResponse } from 'next';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getEventMetrics } from 'queries';
const unitTypes = ['year', 'month', 'hour', 'day'];
export default async (req, res) => {
export interface WebsiteEventsRequestQuery {
id: string;
start_at: string;
end_at: string;
unit: string;
tz: string;
url: string;
event_name: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteEventsRequestQuery>,
res: NextApiResponse<WebsiteMetric>,
) => {
await useCors(req, res);
await useAuth(req, res);
@ -24,9 +40,15 @@ export default async (req, res) => {
const startDate = new Date(+start_at);
const endDate = new Date(+end_at);
const events = await getEventMetrics(websiteId, startDate, endDate, tz, unit, {
url,
eventName: event_name,
const events = await getEventMetrics(websiteId, {
startDate,
endDate,
timezone: tz,
unit,
filters: {
url,
eventName: event_name,
},
});
return ok(res, events);

View file

@ -3,8 +3,24 @@ import { useAuth, useCors } from 'lib/middleware';
import { methodNotAllowed, ok, serverError, unauthorized } from 'next-basics';
import { deleteWebsite, getWebsite, updateWebsite } from 'queries';
import { TYPE_WEBSITE } from 'lib/constants';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
import { Website } from 'interface/api/models';
export default async (req, res) => {
export interface WebsiteReqeustQuery {
id: string;
}
export interface WebsiteReqeustBody {
name: string;
domain: string;
shareId: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteReqeustQuery, WebsiteReqeustBody>,
res: NextApiResponse<Website | any>,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -1,6 +1,9 @@
import { WebsiteMetric } from 'interface/api/models';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { allowQuery } from 'lib/auth';
import { FILTER_IGNORED, TYPE_WEBSITE } from 'lib/constants';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getPageviewMetrics, getSessionMetrics, getWebsite } from 'queries';
@ -33,7 +36,23 @@ function getColumn(type) {
return type;
}
export default async (req, res) => {
export interface WebsiteMetricsReqeustQuery {
id: string;
type: string;
start_at: number;
end_at: number;
url: string;
referrer: string;
os: string;
browser: string;
device: string;
country: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteMetricsReqeustQuery>,
res: NextApiResponse<WebsiteMetric[]>,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -1,13 +1,34 @@
import moment from 'moment-timezone';
import { getPageviewStats } from 'queries';
import { ok, badRequest, methodNotAllowed, unauthorized } from 'next-basics';
import { WebsitePageviews } from 'interface/api/models';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { TYPE_WEBSITE } from 'lib/constants';
import { useAuth, useCors } from 'lib/middleware';
import moment from 'moment-timezone';
import { NextApiResponse } from 'next';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getPageviewStats } from 'queries';
const unitTypes = ['year', 'month', 'hour', 'day'];
export default async (req, res) => {
export interface WebsitePageviewReqeustQuery {
id: string;
websiteId: string;
start_at: number;
end_at: number;
unit: string;
tz: string;
url?: string;
referrer?: string;
os?: string;
browser?: string;
device?: string;
country?: string;
}
export default async (
req: NextApiRequestQueryBody<WebsitePageviewReqeustQuery>,
res: NextApiResponse<WebsitePageviews>,
) => {
await useCors(req, res);
await useAuth(req, res);
@ -39,8 +60,8 @@ export default async (req, res) => {
const [pageviews, sessions] = await Promise.all([
getPageviewStats(websiteId, {
start_at: startDate,
end_at: endDate,
startDate,
endDate,
timezone: tz,
unit,
count: '*',
@ -54,8 +75,8 @@ export default async (req, res) => {
},
}),
getPageviewStats(websiteId, {
start_at: startDate,
end_at: endDate,
startDate,
endDate,
timezone: tz,
unit,
count: 'distinct pageview.',

View file

@ -3,8 +3,17 @@ import { methodNotAllowed, ok, unauthorized } from 'next-basics';
import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { TYPE_WEBSITE } from 'lib/constants';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
export default async (req, res) => {
export interface WebsiteResetReqeustQuery {
id: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteResetReqeustQuery>,
res: NextApiResponse,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -3,8 +3,27 @@ import { methodNotAllowed, ok, unauthorized } from 'next-basics';
import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { TYPE_WEBSITE } from 'lib/constants';
import { WebsiteStats } from 'interface/api/models';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
export default async (req, res) => {
export interface WebsiteStatsReqeustQuery {
id: string;
type: string;
start_at: number;
end_at: number;
url: string;
referrer: string;
os: string;
browser: string;
device: string;
country: string;
}
export default async (
req: NextApiRequestQueryBody<WebsiteStatsReqeustQuery>,
res: NextApiResponse<WebsiteStats>,
) => {
await useCors(req, res);
await useAuth(req, res);

View file

@ -2,8 +2,23 @@ import { createWebsite, getAllWebsites, getUserWebsites } from 'queries';
import { ok, methodNotAllowed, getRandomChars } from 'next-basics';
import { useAuth, useCors } from 'lib/middleware';
import { uuid } from 'lib/crypto';
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
import { NextApiResponse } from 'next';
export default async (req, res) => {
export interface WebsitesReqeustQuery {
include_all?: boolean;
}
export interface WebsitesReqeustBody {
name: string;
domain: string;
enableShareUrl: boolean;
}
export default async (
req: NextApiRequestQueryBody<WebsitesReqeustQuery, WebsitesReqeustBody>,
res: NextApiResponse,
) => {
await useCors(req, res);
await useAuth(req, res);