mirror of
https://github.com/wassname/talk.git
synced 2026-08-09 12:30:42 +08:00
[next] Error and Logging Improvements (#2152)
* feat: added locale support for Tenant * feat: added secret scrubbing to logs * chore: cleanup logger * chore: logger improvements * feat: re-introduce scoped pretty logger * feat: added initial error support * refactor: replace trace-error.TraceError with talk.InternalError * fix: fixed error logging * refactor: replaced Error with VError * fix: repaired issue with error management on api * fix: patched bug with not found handler * feat: added translations * feat: added location path to invalid entries * refactor: refactored error handling on graph * fix: moved indexing operations to master node * refactor: added throw for when the message isn't found in testing * fix: removed duplicate log * fix: fixed naming on environment variable
This commit is contained in:
@@ -3,6 +3,7 @@ import uuid from "uuid";
|
||||
|
||||
import { Omit } from "talk-common/types";
|
||||
import { dotize } from "talk-common/utils/dotize";
|
||||
import { DuplicateStoryURLError } from "talk-server/errors";
|
||||
import { GQLStoryMetadata } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import { createIndexFactory } from "talk-server/models/helpers/query";
|
||||
import { ModerationSettings } from "talk-server/models/settings";
|
||||
@@ -185,8 +186,7 @@ export async function createStory(
|
||||
// Evaluate the error, if it is in regards to violating the unique index,
|
||||
// then return a duplicate Story error.
|
||||
if (err instanceof MongoError && err.code === 11000) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("story with this url already exists");
|
||||
throw new DuplicateStoryURLError(url);
|
||||
}
|
||||
|
||||
throw err;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { isNull, omitBy } from "lodash";
|
||||
import { Db } from "mongodb";
|
||||
import uuid from "uuid";
|
||||
|
||||
import { LanguageCode } from "talk-common/helpers/i18n/locales";
|
||||
import { DeepPartial, Omit, Sub } from "talk-common/types";
|
||||
import { dotize, DotizeOptions } from "talk-common/utils/dotize";
|
||||
import { GQLMODERATION_MODE } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
@@ -38,6 +39,11 @@ export interface Tenant extends Settings {
|
||||
// domains is the list of domains that are allowed to have the iframe load on.
|
||||
domains: string[];
|
||||
|
||||
/**
|
||||
* locale is the specified locale for this Tenant.
|
||||
*/
|
||||
locale: LanguageCode;
|
||||
|
||||
organizationName: string;
|
||||
organizationURL: string;
|
||||
organizationContactEmail: string;
|
||||
@@ -61,10 +67,11 @@ export async function createTenantIndexes(mongo: Db) {
|
||||
export type CreateTenantInput = Pick<
|
||||
Tenant,
|
||||
| "domain"
|
||||
| "domains"
|
||||
| "locale"
|
||||
| "organizationName"
|
||||
| "organizationURL"
|
||||
| "organizationContactEmail"
|
||||
| "domains"
|
||||
>;
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,16 @@ import { Db } from "mongodb";
|
||||
import uuid from "uuid";
|
||||
|
||||
import { Omit, Sub } from "talk-common/types";
|
||||
import {
|
||||
DuplicateEmailError,
|
||||
DuplicateUserError,
|
||||
DuplicateUsernameError,
|
||||
LocalProfileAlreadySetError,
|
||||
LocalProfileNotSetError,
|
||||
TokenNotFoundError,
|
||||
UsernameAlreadySetError,
|
||||
UserNotFoundError,
|
||||
} from "talk-server/errors";
|
||||
import { GQLUSER_ROLE } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import {
|
||||
createIndexFactory,
|
||||
@@ -180,8 +190,7 @@ export async function upsertUser(
|
||||
// because we're returning the updated document and performing an upsert
|
||||
// operation.
|
||||
if (result.value!.id !== id) {
|
||||
// TODO: return better error.
|
||||
throw new Error("user already found");
|
||||
throw new DuplicateUserError();
|
||||
}
|
||||
|
||||
return result.value!;
|
||||
@@ -259,8 +268,7 @@ export async function updateUserRole(
|
||||
}
|
||||
);
|
||||
if (!result.value) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -271,7 +279,7 @@ export async function verifyUserPassword(user: User, password: string) {
|
||||
({ type }) => type === "local"
|
||||
) as LocalProfile | undefined;
|
||||
if (!profile) {
|
||||
throw new Error("no local profile exists for this user");
|
||||
throw new LocalProfileNotSetError();
|
||||
}
|
||||
|
||||
return bcrypt.compare(password, profile.password);
|
||||
@@ -310,8 +318,7 @@ export async function updateUserPassword(
|
||||
if (!result.value) {
|
||||
const user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -319,12 +326,10 @@ export async function updateUserPassword(
|
||||
profile => profile.type === "local" && profile.id === user.email
|
||||
)
|
||||
) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user does not have a local profile");
|
||||
throw new LocalProfileNotSetError();
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value || null;
|
||||
@@ -354,8 +359,7 @@ export async function setUserUsername(
|
||||
lowercaseUsername,
|
||||
});
|
||||
if (user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("duplicate username found");
|
||||
throw new DuplicateUsernameError(username);
|
||||
}
|
||||
|
||||
// The username wasn't found, so add it to the user.
|
||||
@@ -381,17 +385,14 @@ export async function setUserUsername(
|
||||
// Try to get the current user to discover what happened.
|
||||
user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
if (user.username) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user already has username");
|
||||
throw new UsernameAlreadySetError();
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -420,8 +421,7 @@ export async function updateUserUsername(
|
||||
lowercaseUsername,
|
||||
});
|
||||
if (user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("duplicate username found");
|
||||
throw new DuplicateUsernameError(username);
|
||||
}
|
||||
|
||||
// The username wasn't found, so add it to the user.
|
||||
@@ -446,12 +446,10 @@ export async function updateUserUsername(
|
||||
// Try to get the current user to discover what happened.
|
||||
user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -495,12 +493,10 @@ export async function updateUserDisplayName(
|
||||
// Try to get the current user to discover what happened.
|
||||
const user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -530,8 +526,7 @@ export async function setUserEmail(
|
||||
email,
|
||||
});
|
||||
if (user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("duplicate email found");
|
||||
throw new DuplicateEmailError(email);
|
||||
}
|
||||
|
||||
// The email wasn't found, so try to update the User.
|
||||
@@ -556,17 +551,14 @@ export async function setUserEmail(
|
||||
// Try to get the current user to discover what happened.
|
||||
user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
if (user.email) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user already has email");
|
||||
throw new UsernameAlreadySetError();
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -595,8 +587,7 @@ export async function updateUserEmail(
|
||||
email,
|
||||
});
|
||||
if (user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("duplicate email found");
|
||||
throw new DuplicateEmailError(email);
|
||||
}
|
||||
|
||||
// The email wasn't found, so try to update the User.
|
||||
@@ -620,12 +611,10 @@ export async function updateUserEmail(
|
||||
// Try to get the current user to discover what happened.
|
||||
user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -669,12 +658,10 @@ export async function updateUserAvatar(
|
||||
// Try to get the current user to discover what happened.
|
||||
const user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -707,8 +694,7 @@ export async function setUserLocalProfile(
|
||||
id: email,
|
||||
});
|
||||
if (user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("duplicate profile found");
|
||||
throw new DuplicateEmailError(email);
|
||||
}
|
||||
|
||||
// Hash the password.
|
||||
@@ -745,17 +731,14 @@ export async function setUserLocalProfile(
|
||||
// Try to get the current user to discover what happened.
|
||||
user = await retrieveUser(mongo, tenantID, id);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
if (user.profiles.some(({ type }) => type === "local")) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user already has local profile");
|
||||
throw new LocalProfileAlreadySetError();
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("unexpected error occurred");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
return result.value;
|
||||
@@ -789,8 +772,7 @@ export async function createUserToken(
|
||||
}
|
||||
);
|
||||
if (!result.value) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(userID);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -824,18 +806,15 @@ export async function deactivateUserToken(
|
||||
if (!result.value) {
|
||||
const user = await retrieveUser(mongo, tenantID, userID);
|
||||
if (!user) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("user not found");
|
||||
throw new UserNotFoundError(id);
|
||||
}
|
||||
|
||||
// Check to see if the User had that Token in the first place.
|
||||
if (!user.tokens.find(t => t.id === id)) {
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("token not found on user");
|
||||
throw new TokenNotFoundError();
|
||||
}
|
||||
|
||||
// TODO: (wyattjoh) return better error
|
||||
throw new Error("could not remove the token for an unknown reason");
|
||||
throw new Error("an unexpected error occured");
|
||||
}
|
||||
|
||||
// We have to typecast here because we know at this point that the record does
|
||||
|
||||
Reference in New Issue
Block a user