mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
feat(server): improve logs (#8977)
This commit is contained in:
@@ -75,7 +75,7 @@ export class AuthController {
|
||||
@Body() params?: { email: string }
|
||||
): Promise<PreflightResponse> {
|
||||
if (!params?.email) {
|
||||
throw new InvalidEmail();
|
||||
throw new InvalidEmail({ email: 'not provided' });
|
||||
}
|
||||
validators.assertValidEmail(params.email);
|
||||
|
||||
@@ -171,7 +171,7 @@ export class AuthController {
|
||||
// verify domain has MX, SPF, DMARC records
|
||||
const [name, domain, ...rest] = email.split('@');
|
||||
if (rest.length || !domain) {
|
||||
throw new InvalidEmail();
|
||||
throw new InvalidEmail({ email });
|
||||
}
|
||||
const [mx, spf, dmarc] = await Promise.allSettled([
|
||||
resolveMx(domain).then(t => t.map(mx => mx.exchange).filter(Boolean)),
|
||||
@@ -183,11 +183,11 @@ export class AuthController {
|
||||
),
|
||||
]).then(t => t.filter(t => t.status === 'fulfilled').map(t => t.value));
|
||||
if (!mx?.length || !spf?.length || !dmarc?.length) {
|
||||
throw new InvalidEmail();
|
||||
throw new InvalidEmail({ email });
|
||||
}
|
||||
// filter out alias emails
|
||||
if (name.includes('+') || name.includes('.')) {
|
||||
throw new InvalidEmail();
|
||||
throw new InvalidEmail({ email });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { InvalidEmail, InvalidPasswordLength } from '../../fundamentals';
|
||||
export function assertValidEmail(email: string) {
|
||||
const result = z.string().email().safeParse(email);
|
||||
if (!result.success) {
|
||||
throw new InvalidEmail();
|
||||
throw new InvalidEmail({ email });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,12 @@ export class UserFriendlyError extends Error {
|
||||
log(context: string) {
|
||||
// ignore all user behavior error log
|
||||
if (this.type !== 'internal_server_error') {
|
||||
return;
|
||||
// always record auth related error
|
||||
const isAuthError =
|
||||
typeof this.stack === 'string' &&
|
||||
(this.stack.includes('/core/auth/') ||
|
||||
this.stack.includes('/plugins/oauth/'));
|
||||
if (!isAuthError) return;
|
||||
}
|
||||
|
||||
new Logger(context).error(
|
||||
@@ -261,7 +266,8 @@ export const USER_FRIENDLY_ERRORS = {
|
||||
},
|
||||
invalid_email: {
|
||||
type: 'invalid_input',
|
||||
message: 'An invalid email provided.',
|
||||
args: { email: 'string' },
|
||||
message: ({ email }) => `An invalid email provided: ${email}`,
|
||||
},
|
||||
invalid_password_length: {
|
||||
type: 'invalid_input',
|
||||
|
||||
@@ -89,10 +89,14 @@ export class OauthAccountAlreadyConnected extends UserFriendlyError {
|
||||
super('bad_request', 'oauth_account_already_connected', message);
|
||||
}
|
||||
}
|
||||
@ObjectType()
|
||||
class InvalidEmailDataType {
|
||||
@Field() email!: string
|
||||
}
|
||||
|
||||
export class InvalidEmail extends UserFriendlyError {
|
||||
constructor(message?: string) {
|
||||
super('invalid_input', 'invalid_email', message);
|
||||
constructor(args: InvalidEmailDataType, message?: string | ((args: InvalidEmailDataType) => string)) {
|
||||
super('invalid_input', 'invalid_email', message, args);
|
||||
}
|
||||
}
|
||||
@ObjectType()
|
||||
@@ -620,5 +624,5 @@ registerEnumType(ErrorNames, {
|
||||
export const ErrorDataUnionType = createUnionType({
|
||||
name: 'ErrorDataUnion',
|
||||
types: () =>
|
||||
[UnknownOauthProviderDataType, MissingOauthQueryParameterDataType, InvalidPasswordLengthDataType, SpaceNotFoundDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, DocNotFoundDataType, DocAccessDeniedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType] as const,
|
||||
[UnknownOauthProviderDataType, MissingOauthQueryParameterDataType, InvalidEmailDataType, InvalidPasswordLengthDataType, SpaceNotFoundDataType, NotInSpaceDataType, AlreadyInSpaceDataType, SpaceAccessDeniedDataType, SpaceOwnerNotFoundDataType, DocNotFoundDataType, DocAccessDeniedDataType, VersionRejectedDataType, InvalidHistoryTimestampDataType, DocHistoryNotFoundDataType, BlobNotFoundDataType, SubscriptionAlreadyExistsDataType, SubscriptionNotExistsDataType, SameSubscriptionRecurringDataType, SubscriptionPlanNotFoundDataType, CopilotMessageNotFoundDataType, CopilotPromptNotFoundDataType, CopilotProviderSideErrorDataType, RuntimeConfigNotFoundDataType, InvalidRuntimeConfigTypeDataType] as const,
|
||||
});
|
||||
|
||||
@@ -43,9 +43,12 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
|
||||
);
|
||||
error.log('GraphQL');
|
||||
|
||||
metrics.gql
|
||||
.counter('query_error_counter')
|
||||
.add(1, { operation, code: error.status });
|
||||
metrics.gql.counter('query_error_counter').add(1, {
|
||||
operation,
|
||||
code: error.status,
|
||||
type: error.type,
|
||||
error: error.name,
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.resolve();
|
||||
|
||||
@@ -46,7 +46,9 @@ export class GlobalExceptionFilter extends BaseExceptionFilter {
|
||||
throw error;
|
||||
} else {
|
||||
error.log('HTTP');
|
||||
metrics.controllers.counter('error').add(1, { status: error.status });
|
||||
metrics.controllers
|
||||
.counter('error')
|
||||
.add(1, { status: error.status, type: error.type, error: error.name });
|
||||
const res = host.switchToHttp().getResponse<Response>();
|
||||
const respondText = res.getHeader('content-type') === 'text/plain';
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ type EditorType {
|
||||
name: String!
|
||||
}
|
||||
|
||||
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderSideErrorDataType | DocAccessDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | InvalidHistoryTimestampDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | MissingOauthQueryParameterDataType | NotInSpaceDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | VersionRejectedDataType
|
||||
union ErrorDataUnion = AlreadyInSpaceDataType | BlobNotFoundDataType | CopilotMessageNotFoundDataType | CopilotPromptNotFoundDataType | CopilotProviderSideErrorDataType | DocAccessDeniedDataType | DocHistoryNotFoundDataType | DocNotFoundDataType | InvalidEmailDataType | InvalidHistoryTimestampDataType | InvalidPasswordLengthDataType | InvalidRuntimeConfigTypeDataType | MissingOauthQueryParameterDataType | NotInSpaceDataType | RuntimeConfigNotFoundDataType | SameSubscriptionRecurringDataType | SpaceAccessDeniedDataType | SpaceNotFoundDataType | SpaceOwnerNotFoundDataType | SubscriptionAlreadyExistsDataType | SubscriptionNotExistsDataType | SubscriptionPlanNotFoundDataType | UnknownOauthProviderDataType | VersionRejectedDataType
|
||||
|
||||
enum ErrorNames {
|
||||
ACCESS_DENIED
|
||||
@@ -315,6 +315,10 @@ type HumanReadableQuotaType {
|
||||
storageQuota: String!
|
||||
}
|
||||
|
||||
type InvalidEmailDataType {
|
||||
email: String!
|
||||
}
|
||||
|
||||
type InvalidHistoryTimestampDataType {
|
||||
timestamp: String!
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ test('should not be able to sign in if email is invalid', async t => {
|
||||
.send({ email: '' })
|
||||
.expect(400);
|
||||
|
||||
t.is(res.body.message, 'An invalid email provided.');
|
||||
t.is(res.body.message, 'An invalid email provided: ');
|
||||
});
|
||||
|
||||
test('should not be able to sign in if forbidden', async t => {
|
||||
|
||||
Reference in New Issue
Block a user