This commit is contained in:
Simon Larsen
2022-09-12 20:55:56 +01:00
parent 2f933aa6a9
commit 7a5fd1dfc1
44 changed files with 520 additions and 503 deletions

View File

@@ -152,10 +152,10 @@ export default class BaseModel extends BaseEntity {
return dictionary[columnName] as TableColumnMetadata;
}
public getColumnAccessControlFor(columnName: string): ColumnAccessControl | null {
return (
this.getColumnAccessControlForAllColumns()[columnName] || null
);
public getColumnAccessControlFor(
columnName: string
): ColumnAccessControl | null {
return this.getColumnAccessControlForAllColumns()[columnName] || null;
}
public getColumnAccessControlForAllColumns(): Dictionary<ColumnAccessControl> {
@@ -278,11 +278,27 @@ export default class BaseModel extends BaseEntity {
for (const key of Object.keys(json)) {
const tableColumnMetadata = baseModel.getTableColumnMetadata(key);
if (tableColumnMetadata) {
if (json[key] && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.Entity) {
(baseModel as any)[key] = new tableColumnMetadata.modelType().fromJSON(json[key] as JSONObject, tableColumnMetadata.modelType);
} else if (json[key] && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.EntityArray) {
(baseModel as any)[key] = new tableColumnMetadata.modelType().fromJSONArray(json[key] as JSONArray, tableColumnMetadata.modelType);
} else {
if (
json[key] &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.Entity
) {
(baseModel as any)[key] =
new tableColumnMetadata.modelType().fromJSON(
json[key] as JSONObject,
tableColumnMetadata.modelType
);
} else if (
json[key] &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.EntityArray
) {
(baseModel as any)[key] =
new tableColumnMetadata.modelType().fromJSONArray(
json[key] as JSONArray,
tableColumnMetadata.modelType
);
} else {
(baseModel as any)[key] = json[key];
}
}
@@ -376,7 +392,6 @@ export default class BaseModel extends BaseEntity {
);
}
public isFileColumn(columnName: string): boolean {
const tableColumnType: TableColumnMetadata = getTableColumn(
this,
@@ -393,37 +408,56 @@ export default class BaseModel extends BaseEntity {
return true;
}
return false;
return false;
}
public static toJSON(model: BaseModel, modelType: { new (): BaseModel }): JSONObject {
public static toJSON(
model: BaseModel,
modelType: { new (): BaseModel }
): JSONObject {
const json: JSONObject = this.toJSONObject(model, modelType);
return JSONFunctions.serialize(json);
}
public static toJSONObject(model: BaseModel, modelType: { new(): BaseModel }): JSONObject {
public static toJSONObject(
model: BaseModel,
modelType: { new (): BaseModel }
): JSONObject {
const json: JSONObject = {};
const vanillaModel = new modelType();
for (const key of vanillaModel.getTableColumns().columns) {
if (
(model as any)[key] === undefined
) {
if ((model as any)[key] === undefined) {
continue;
}
const tableColumnMetadata = vanillaModel.getTableColumnMetadata(key);
const tableColumnMetadata =
vanillaModel.getTableColumnMetadata(key);
if (tableColumnMetadata) {
if ((model as any)[key] && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.Entity && (model as any)[key] instanceof BaseModel) {
(json as any)[key] = BaseModel.toJSONObject((model as any)[key], tableColumnMetadata.modelType);
} else if ((model as any)[key] && Array.isArray((model as any)[key]) && (model as any)[key].length > 0 && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.EntityArray) {
(json as any)[key] = BaseModel.toJSONObjectArray((model as any)[key] as Array<BaseModel>, tableColumnMetadata.modelType);
} else {
if (
(model as any)[key] &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.Entity &&
(model as any)[key] instanceof BaseModel
) {
(json as any)[key] = BaseModel.toJSONObject(
(model as any)[key],
tableColumnMetadata.modelType
);
} else if (
(model as any)[key] &&
Array.isArray((model as any)[key]) &&
(model as any)[key].length > 0 &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.EntityArray
) {
(json as any)[key] = BaseModel.toJSONObjectArray(
(model as any)[key] as Array<BaseModel>,
tableColumnMetadata.modelType
);
} else {
(json as any)[key] = (model as any)[key];
}
}
@@ -432,7 +466,10 @@ export default class BaseModel extends BaseEntity {
return json;
}
public static toJSONObjectArray(list: Array<BaseModel>, modelType: { new (): BaseModel } ): JSONArray {
public static toJSONObjectArray(
list: Array<BaseModel>,
modelType: { new (): BaseModel }
): JSONArray {
const array: JSONArray = [];
for (const item of list) {
@@ -442,7 +479,10 @@ export default class BaseModel extends BaseEntity {
return array;
}
public static toJSONArray(list: Array<BaseModel>, modelType: { new (): BaseModel }): JSONArray {
public static toJSONArray(
list: Array<BaseModel>,
modelType: { new (): BaseModel }
): JSONArray {
const array: JSONArray = [];
for (const item of list) {
@@ -500,7 +540,7 @@ export default class BaseModel extends BaseEntity {
this.getColumnAccessControlFor(columnName);
if (columnAccessControl) {
modelPermission = columnAccessControl.read;
}
}
}
return this.hasPermissions(userProjectPermissions, modelPermission);

View File

@@ -10,7 +10,6 @@ import BaseModel from './BaseModel';
@SlugifyColumn('name', 'slug')
export default class FileModel extends BaseModel {
public constructor(id?: ObjectID) {
super(id);
}

View File

@@ -125,16 +125,14 @@ export class JSONFunctions {
const newVal: JSONValue = {};
for (const key in val) {
if (val[key] === undefined) {
continue;
}
if (val[key] === null) {
if (val[key] === null) {
newVal[key] = val[key];
}
if (Array.isArray(val[key])) {
const arraySerialize: Array<JSONValue> = [];
for (const arrVal of val[key] as Array<JSONValue>) {
@@ -170,7 +168,7 @@ export class JSONFunctions {
_type: ObjectType.Name,
value: (val as Name).toString(),
};
} else if (val && val instanceof Domain) {
} else if (val && val instanceof Domain) {
return {
_type: ObjectType.Domain,
value: (val as Domain).toString(),
@@ -295,13 +293,14 @@ export class JSONFunctions {
ObjectType.Buffer &&
((val as JSONObject)['_type'] as string) === ObjectType.Buffer
) {
return Buffer.from(((val as JSONObject)['value'] as JSONObject)['data'] as Uint8Array);
}else if (
val &&
ArrayBuffer.isView(val)
) {
return Buffer.from(
((val as JSONObject)['value'] as JSONObject)[
'data'
] as Uint8Array
);
} else if (val && ArrayBuffer.isView(val)) {
return Buffer.from(val as Uint8Array);
} else if (typeof val === Typeof.Number) {
} else if (typeof val === Typeof.Number) {
return val;
} else if (val instanceof DatabaseProperty) {
return val;
@@ -314,7 +313,7 @@ export class JSONFunctions {
((val as JSONObject)['_type'] as string) === ObjectType.Name
) {
return new Name((val as JSONObject)['value'] as string);
}else if (
} else if (
val &&
typeof val === Typeof.Object &&
(val as JSONObject)['_type'] &&

View File

@@ -61,19 +61,17 @@ enum Permission {
CanEditProjectIncident = 'CanEditProjectIncident',
CanReadProjectIncident = 'CanReadProjectIncident',
// Probe Permissions (Owner Permission)
CanCreateProjectDomain = 'CanCreateProjectDomain',
CanDeleteProjectDomain = 'CanDeleteProjectDomain',
CanEditProjectDomain = 'CanEditProjectDomain',
CanReadProjectDomain = 'CanReadProjectDomain',
// Probe Permissions (Owner Permission)
CanCreateStatusPageResource = 'CanCreateStatusPageResource',
CanDeleteStatusPageResource = 'CanDeleteStatusPageResource',
CanEditStatusPageResource = 'CanEditStatusPageResource',
CanReadStatusPageResource = 'CanReadStatusPageResource',
// Probe Permissions (Owner Permission)
CanCreateStatusPageResource = 'CanCreateStatusPageResource',
CanDeleteStatusPageResource = 'CanDeleteStatusPageResource',
CanEditStatusPageResource = 'CanEditStatusPageResource',
CanReadStatusPageResource = 'CanReadStatusPageResource',
// Probe Permissions (Owner Permission)
CanCreateStatusPageGroup = 'CanCreateStatusPageGroup',
@@ -81,11 +79,11 @@ enum Permission {
CanEditStatusPageGroup = 'CanEditStatusPageGroup',
CanReadStatusPageGroup = 'CanReadStatusPageGroup',
// Probe Permissions (Owner Permission)
CanCreateStatusPageDomain = 'CanCreateStatusPageDomain',
CanDeleteStatusPageDomain = 'CanDeleteStatusPageDomain',
CanEditStatusPageDomain = 'CanEditStatusPageDomain',
CanReadStatusPageDomain = 'CanReadStatusPageDomain',
// Probe Permissions (Owner Permission)
CanCreateStatusPageDomain = 'CanCreateStatusPageDomain',
CanDeleteStatusPageDomain = 'CanDeleteStatusPageDomain',
CanEditStatusPageDomain = 'CanEditStatusPageDomain',
CanReadStatusPageDomain = 'CanReadStatusPageDomain',
// Label Permissions (Owner + Admin Permission by default)
CanCreateProjectLabel = 'CanCreateProjectLabel',
@@ -459,10 +457,7 @@ export class PermissionHelper {
description:
'A user assigned this permission can read incident state in this project.',
isAssignableToProject: true,
},
},
{
permission: Permission.CanCreateProjectDomain,
@@ -492,8 +487,6 @@ export class PermissionHelper {
'A user assigned this permission can read Domain in this project.',
isAssignableToProject: true,
},
{
permission: Permission.CanCreateStatusPageResource,
@@ -524,10 +517,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateStatusPageGroup,
title: 'Can Create Status Page Group',
@@ -557,8 +546,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateStatusPageDomain,
title: 'Can Create Status Page Domain',
@@ -588,8 +575,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateProjectSMTPConfig,
title: 'Can Create SMTP Config',
@@ -619,9 +604,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateStatusPageDomain,
title: 'Can Create Status Page Domain',
@@ -651,8 +633,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateIncidentSeverity,
title: 'Can Create Incident Severity',
@@ -682,9 +662,6 @@ export class PermissionHelper {
isAssignableToProject: true,
},
{
permission: Permission.CanCreateProjectTeam,
title: 'Can Create Team',

View File

@@ -189,7 +189,6 @@ export default class BaseAPI<
req: ExpressRequest,
res: ExpressResponse
): Promise<void> {
const skip: PositiveNumber = req.query['skip']
? new PositiveNumber(req.query['skip'] as string)
: new PositiveNumber(0);
@@ -247,7 +246,13 @@ export default class BaseAPI<
props: databaseProps,
});
return Response.sendListResponse(req, res, list, count, this.entityType);
return Response.sendListResponse(
req,
res,
list,
count,
this.entityType
);
}
public async count(
@@ -270,7 +275,12 @@ export default class BaseAPI<
props: databaseProps,
});
return Response.sendItemResponse(req, res, { count: count.toNumber() }, this.entityType);
return Response.sendItemResponse(
req,
res,
{ count: count.toNumber() },
this.entityType
);
}
public async getItem(
@@ -301,7 +311,12 @@ export default class BaseAPI<
props: this.getDatabaseCommonInteractionProps(req),
});
return Response.sendItemResponse(req, res, item ? BaseModel.toJSON(item, this.entityType) : {}, this.entityType);
return Response.sendItemResponse(
req,
res,
item ? BaseModel.toJSON(item, this.entityType) : {},
this.entityType
);
}
public async deleteItem(

View File

@@ -701,7 +701,9 @@ class DatabaseService<TBaseModel extends BaseModel> {
throw new NotAuthorizedException(
`You do not have permissions to query on - ${key}. You need any one of these permissions: ${PermissionHelper.getPermissionTitles(
this.model.getColumnAccessControlFor(key) ? this.model.getColumnAccessControlFor(key)!.read : []
this.model.getColumnAccessControlFor(key)
? this.model.getColumnAccessControlFor(key)!.read
: []
).join(',')}`
);
}
@@ -722,7 +724,9 @@ class DatabaseService<TBaseModel extends BaseModel> {
throw new NotAuthorizedException(
`You do not have permissions to select on - ${key}.
You need any one of these permissions: ${PermissionHelper.getPermissionTitles(
this.model.getColumnAccessControlFor(key) ? this.model.getColumnAccessControlFor(key)!.read : []
this.model.getColumnAccessControlFor(key)
? this.model.getColumnAccessControlFor(key)!.read
: []
).join(',')}`
);
}
@@ -831,7 +835,9 @@ class DatabaseService<TBaseModel extends BaseModel> {
throw new NotAuthorizedException(
`You do not have permissions to update this record at - ${key}.
You need any one of these permissions: ${PermissionHelper.getPermissionTitles(
this.model.getColumnAccessControlFor(key) ? this.model.getColumnAccessControlFor(key)!.update : []
this.model.getColumnAccessControlFor(key)
? this.model.getColumnAccessControlFor(key)!.update
: []
).join(',')}`
);
}
@@ -1372,16 +1378,17 @@ class DatabaseService<TBaseModel extends BaseModel> {
);
if (!hasPermission) {
let readPermissions: Array<Permission> = [];
if (relatedModel.getColumnAccessControlFor(
innerKey
)) {
readPermissions = relatedModel.getColumnAccessControlFor(
if (
relatedModel.getColumnAccessControlFor(
innerKey
)!.read;
)
) {
readPermissions =
relatedModel.getColumnAccessControlFor(
innerKey
)!.read;
}
throw new NotAuthorizedException(
`You do not have permissions to read ${key}.${innerKey} on ${

View File

@@ -2,7 +2,7 @@ import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/Domain';
import DatabaseService, { OnCreate, OnUpdate } from './DatabaseService';
import CreateBy from '../Types/Database/CreateBy';
import Text from "Common/Types/Text";
import Text from 'Common/Types/Text';
import UpdateBy from '../Types/Database/UpdateBy';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Domain from '../Types/Domain';
@@ -15,15 +15,22 @@ export class Service extends DatabaseService<Model> {
protected override async onBeforeCreate(
createBy: CreateBy<Model>
): Promise<OnCreate<Model>> {
createBy.data.domainVerificationText = 'oneuptime-verification-' + Text.generateRandomText(20);
createBy.data.isVerified = false;
createBy.data.domainVerificationText =
'oneuptime-verification-' + Text.generateRandomText(20);
createBy.data.isVerified = false;
return Promise.resolve({ createBy, carryForward: null });
}
protected override async onBeforeUpdate(updateBy: UpdateBy<Model>): Promise<OnUpdate<Model>> {
debugger;
if (updateBy.data.isVerified && updateBy.query._id && !updateBy.props.isRoot) {
// check the verification of the domain.
protected override async onBeforeUpdate(
updateBy: UpdateBy<Model>
): Promise<OnUpdate<Model>> {
debugger;
if (
updateBy.data.isVerified &&
updateBy.query._id &&
!updateBy.props.isRoot
) {
// check the verification of the domain.
const items = await this.findBy({
query: {
@@ -32,7 +39,7 @@ export class Service extends DatabaseService<Model> {
},
select: {
domain: true,
domainVerificationText: true,
domainVerificationText: true,
},
populate: {},
limit: 1,
@@ -41,30 +48,47 @@ export class Service extends DatabaseService<Model> {
isRoot: true,
},
});
if (items.length === 0) {
throw new BadDataException("Domain with id " + updateBy.query._id + " not found.");
throw new BadDataException(
'Domain with id ' + updateBy.query._id + ' not found.'
);
}
const domain = items[0]?.domain?.toString();
const verificationText = items[0]?.domainVerificationText?.toString();
const verificationText =
items[0]?.domainVerificationText?.toString();
if (!domain) {
throw new BadDataException("Domain with id " + updateBy.query._id + " not found.");
throw new BadDataException(
'Domain with id ' + updateBy.query._id + ' not found.'
);
}
if (!verificationText) {
throw new BadDataException("Domain verification text with id " + updateBy.query._id + " not found.");
throw new BadDataException(
'Domain verification text with id ' +
updateBy.query._id +
' not found.'
);
}
const isVerified = await Domain.verifyTxtRecord(domain, verificationText);
const isVerified = await Domain.verifyTxtRecord(
domain,
verificationText
);
if (!isVerified) {
throw new BadDataException("Verification TXT record "+verificationText+" not found in domain "+domain+". Please add a TXT record to verify the domain.");
throw new BadDataException(
'Verification TXT record ' +
verificationText +
' not found in domain ' +
domain +
'. Please add a TXT record to verify the domain.'
);
}
}
return { carryForward: null, updateBy };
}
}

View File

@@ -27,7 +27,9 @@ export class Service extends DatabaseService<Model> {
}
if (!createBy.data.projectId) {
throw new BadDataException('Incient severity projectId is required');
throw new BadDataException(
'Incient severity projectId is required'
);
}
await this.rearrangeOrder(

View File

@@ -22,7 +22,7 @@ import MonitorStatusService from './MonitorStatusService';
import IncidentState from 'Model/Models/IncidentState';
import IncidentStateService from './IncidentStateService';
import IncidentSeverity from 'Model/Models/IncidentSeverity';
import IncidentSeverityService from "./IncidentSeverityService";
import IncidentSeverityService from './IncidentSeverityService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
@@ -82,7 +82,6 @@ export class Service extends DatabaseService<Model> {
_onCreate: OnCreate<Model>,
createdItem: Model
): Promise<Model> {
createdItem = await this.addDefaultProjectTeams(createdItem);
createdItem = await this.addDefaultMonitorStatus(createdItem);
createdItem = await this.addDefaultIncidentState(createdItem);
@@ -143,7 +142,9 @@ export class Service extends DatabaseService<Model> {
return createdItem;
}
private async addDefaultIncidentSeverity(createdItem: Model): Promise<Model> {
private async addDefaultIncidentSeverity(
createdItem: Model
): Promise<Model> {
let criticalIncident: IncidentSeverity = new IncidentSeverity();
criticalIncident.name = 'Critial Incident';
criticalIncident.description =
@@ -241,8 +242,6 @@ export class Service extends DatabaseService<Model> {
return createdItem;
}
private async addDefaultProjectTeams(createdItem: Model): Promise<Model> {
// add a team member.

View File

@@ -1,8 +1,11 @@
import DomainCommon from "Common/Types/Domain";
import DomainCommon from 'Common/Types/Domain';
import dns from 'dns';
export default class Domain extends DomainCommon {
public static verifyTxtRecord(domain: Domain | string, verificationText: string): Promise<boolean> {
public static verifyTxtRecord(
domain: Domain | string,
verificationText: string
): Promise<boolean> {
return new Promise((resolve, reject) => {
dns.resolveTxt(domain.toString(), (err, data) => {
if (err) {
@@ -23,8 +26,7 @@ export default class Domain extends DomainCommon {
}
resolve(isVerified);
})
})
});
});
}
}
}

View File

@@ -150,7 +150,10 @@ export default class Response {
}
if (list.length > 0 && list[0] instanceof BaseModel) {
listData.data = BaseModel.toJSONArray(list as Array<BaseModel>, modelType);
listData.data = BaseModel.toJSONArray(
list as Array<BaseModel>,
modelType
);
} else {
listData.data = list as JSONArray;
}

View File

@@ -52,18 +52,29 @@ const Detail: Function = (props: ComponentProps): ReactElement => {
}
if (field.fieldType === FieldType.ImageFile) {
if (props.item[fieldKey] && (props.item[fieldKey] as FileModel).file && (props.item[fieldKey] as FileModel).type) {
const blob = new Blob([(props.item[fieldKey] as FileModel).file as Uint8Array], {
type: (props.item[fieldKey] as FileModel).type as string,
});
if (
props.item[fieldKey] &&
(props.item[fieldKey] as FileModel).file &&
(props.item[fieldKey] as FileModel).type
) {
const blob = new Blob(
[(props.item[fieldKey] as FileModel).file as Uint8Array],
{
type: (props.item[fieldKey] as FileModel)
.type as string,
}
);
const url: string = URL.createObjectURL(blob);
data = <img src={url} style={{
height: "100px"
}} />
data = (
<img
src={url}
style={{
height: '100px',
}}
/>
);
} else {
data = '';
}

View File

@@ -31,7 +31,6 @@ export interface ComponentProps {
dataTestId?: string;
isMultiFilePicker?: boolean | undefined;
tabIndex?: number | undefined;
}
const FilePicker: FunctionComponent<ComponentProps> = (
@@ -41,20 +40,26 @@ const FilePicker: FunctionComponent<ComponentProps> = (
const [error, setError] = useState<string>('');
const [filesModel, setFilesModel] = useState<Array<FileModel>>([]);
const [acceptTypes, setAcceptTypes] = useState<Dictionary<Array<string>>>({});
const [acceptTypes, setAcceptTypes] = useState<Dictionary<Array<string>>>(
{}
);
useEffect(() => {
const _acceptTypes:Dictionary<Array<string>> = {};
const _acceptTypes: Dictionary<Array<string>> = {};
if (props.mimeTypes) {
for (const key of props.mimeTypes) {
_acceptTypes[key] = [];
}
}
setAcceptTypes(_acceptTypes);
}, [props.mimeTypes])
}, [props.mimeTypes]);
useEffect(() => {
if (Array.isArray(props.initialValue) && props.initialValue && props.initialValue.length > 0) {
if (
Array.isArray(props.initialValue) &&
props.initialValue &&
props.initialValue.length > 0
) {
setFilesModel(props.initialValue);
} else if (props.initialValue instanceof FileModel) {
setFilesModel([props.initialValue as FileModel]);
@@ -81,12 +86,9 @@ const FilePicker: FunctionComponent<ComponentProps> = (
const fileModel: FileModel = new FileModel();
fileModel.name = acceptedFile.name;
const arrayBuffer = await acceptedFile.arrayBuffer();
const blob = new Blob([new Uint8Array(arrayBuffer)]);
const _url: string = URL.createObjectURL(blob);
const url: string = URL.createObjectURL(acceptedFile);
@@ -94,7 +96,7 @@ const FilePicker: FunctionComponent<ComponentProps> = (
console.log(_url);
console.log(url);
const fileBuffer = new Uint8Array(arrayBuffer)
const fileBuffer = new Uint8Array(arrayBuffer);
fileModel.file = Buffer.from(fileBuffer);
fileModel.isPublic = false;
fileModel.type = acceptedFile.type as MimeType;
@@ -188,7 +190,10 @@ const FilePicker: FunctionComponent<ComponentProps> = (
className: 'file-picker-dropzone',
})}
>
<input tabIndex={props.tabIndex} {...getInputProps()} />
<input
tabIndex={props.tabIndex}
{...getInputProps()}
/>
{!props.placeholder && !error && (
<p className="file-picker-placeholder">
Drag and drop some files here, or click to

View File

@@ -102,8 +102,7 @@ const BasicForm: Function = <T extends Object>(
index: number,
isDisabled: boolean
): ReactElement => {
index = index + 1;
index = index + 1;
const fieldType: string = field.fieldType
? getFieldType(field.fieldType)
@@ -344,7 +343,8 @@ const BasicForm: Function = <T extends Object>(
</Field>
)}
{(field.fieldType === FormFieldSchemaType.File || field.fieldType === FormFieldSchemaType.ImageFile) && (
{(field.fieldType === FormFieldSchemaType.File ||
field.fieldType === FormFieldSchemaType.ImageFile) && (
<Field name={fieldName}>
{({ form }: any) => {
return (
@@ -354,18 +354,26 @@ const BasicForm: Function = <T extends Object>(
onChange={async (
files: Array<FileModel>
) => {
let fileResult: FileModel | Array<FileModel> | null = files.map((i) => {
const strippedModel = new FileModel();
strippedModel._id = i._id!;
let fileResult:
| FileModel
| Array<FileModel>
| null = files.map((i) => {
const strippedModel =
new FileModel();
strippedModel._id = i._id!;
return strippedModel;
});
});
if (field.fieldType === FormFieldSchemaType.File && Array.isArray(fileResult)) {
if (
field.fieldType ===
FormFieldSchemaType.File &&
Array.isArray(fileResult)
) {
if (fileResult.length > 0) {
fileResult = fileResult[0] as FileModel;
fileResult =
fileResult[0] as FileModel;
} else {
fileResult = null;
fileResult = null;
}
}
@@ -381,11 +389,16 @@ const BasicForm: Function = <T extends Object>(
true
);
}}
mimeTypes={field.fieldType === FormFieldSchemaType.ImageFile ? [
MimeType.png,
MimeType.jpeg,
MimeType.jpg
]: []}
mimeTypes={
field.fieldType ===
FormFieldSchemaType.ImageFile
? [
MimeType.png,
MimeType.jpeg,
MimeType.jpg,
]
: []
}
initialValue={
initialValues &&
(initialValues as any)[fieldName]

View File

@@ -42,13 +42,13 @@ export enum FormType {
}
export interface ComponentProps<TBaseModel extends BaseModel> {
modelType: { new(): TBaseModel };
modelType: { new (): TBaseModel };
id: string;
onValidate?:
| undefined
| ((
values: FormValues<TBaseModel>
) => FormikErrors<FormValues<TBaseModel>>);
| undefined
| ((
values: FormValues<TBaseModel>
) => FormikErrors<FormValues<TBaseModel>>);
fields: Fields<TBaseModel>;
submitButtonText?: undefined | string;
title?: undefined | string;
@@ -57,8 +57,8 @@ export interface ComponentProps<TBaseModel extends BaseModel> {
footer: ReactElement;
onCancel?: undefined | (() => void);
onSuccess?:
| undefined
| ((data: TBaseModel | JSONObjectOrArray | Array<TBaseModel>) => void);
| undefined
| ((data: TBaseModel | JSONObjectOrArray | Array<TBaseModel>) => void);
cancelButtonText?: undefined | string;
maxPrimaryButtonWidth?: undefined | boolean;
apiUrl?: undefined | URL;
@@ -113,10 +113,9 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
file: true,
_id: true,
type: true,
name: true
name: true,
};
} else if (key && model.isEntityColumn(key)) {
(populate as JSONObject)[key] = (field.field as any)[key];
}
}
@@ -197,7 +196,10 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
);
if (!(item instanceof BaseModel) && item) {
item = new props.modelType().fromJSON(item as JSONObject, props.modelType);
item = new props.modelType().fromJSON(
item as JSONObject,
props.modelType
);
}
if (!item) {
@@ -223,7 +225,7 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
isModelArray = true;
idArray.push(
(itemInArray as any as JSONObject)[
'_id'
'_id'
] as string
);
}
@@ -234,7 +236,11 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
(item as any)[key] = idArray;
}
}
if ((item as any)[key] && typeof (item as any)[key] === 'object' && !((item as any)[key] instanceof FileModel)) {
if (
(item as any)[key] &&
typeof (item as any)[key] === 'object' &&
!((item as any)[key] instanceof FileModel)
) {
if (((item as any)[key] as JSONObject)['_id']) {
(item as any)[key] = ((item as any)[key] as JSONObject)[
'_id'
@@ -298,7 +304,7 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
try {
setError(
(err as HTTPErrorResponse).message ||
'Server Error. Please try again'
'Server Error. Please try again'
);
} catch (e) {
setError('Server Error. Please try again');
@@ -378,21 +384,33 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
delete valuesToSend[key];
}
for (const key of model.getTableColumns().columns) {
const tableColumnMetadata = model.getTableColumnMetadata(key);
if (tableColumnMetadata && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.Entity && valuesToSend[key] && typeof valuesToSend[key] === Typeof.String) {
let baseModel = new tableColumnMetadata.modelType();
if (
tableColumnMetadata &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.Entity &&
valuesToSend[key] &&
typeof valuesToSend[key] === Typeof.String
) {
const baseModel = new tableColumnMetadata.modelType();
baseModel._id = valuesToSend[key] as string;
valuesToSend[key] = baseModel;
}
if (tableColumnMetadata && tableColumnMetadata.modelType && tableColumnMetadata.type === TableColumnType.EntityArray && Array.isArray(valuesToSend[key]) && (valuesToSend[key] as Array<any>).length > 0 && typeof ((valuesToSend[key] as Array<any>)[0]) === Typeof.String) {
if (
tableColumnMetadata &&
tableColumnMetadata.modelType &&
tableColumnMetadata.type === TableColumnType.EntityArray &&
Array.isArray(valuesToSend[key]) &&
(valuesToSend[key] as Array<any>).length > 0 &&
typeof (valuesToSend[key] as Array<any>)[0] ===
Typeof.String
) {
const arr: Array<BaseModel> = [];
for (const id of valuesToSend[key] as Array<string>) {
let baseModel = new tableColumnMetadata.modelType();
const baseModel = new tableColumnMetadata.modelType();
baseModel._id = id as string;
arr.push(baseModel);
}
@@ -409,7 +427,6 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
tBaseModel = await props.onBeforeCreate(tBaseModel);
}
result = await ModelAPI.createOrUpdate<TBaseModel>(
tBaseModel,
props.modelType,
@@ -425,7 +442,7 @@ const ModelForm: Function = <TBaseModel extends BaseModel>(
} catch (err) {
setError(
(err as HTTPErrorResponse).message ||
'Server Error. Please try again'
'Server Error. Please try again'
);
}

View File

@@ -11,7 +11,7 @@ enum FormFieldSchemaType {
Email,
PositveNumber,
Date,
Phone,
Phone,
Domain,
LongText,
Color,

View File

@@ -30,9 +30,9 @@ const ListRow: FunctionComponent<ComponentProps> = (
{props.actionButtons?.map(
(button: ActionButtonSchema, i: number) => {
if (button.isVisible && !button.isVisible(props.item)) {
return <></>
return <></>;
}
return (
<span
style={

View File

@@ -10,7 +10,7 @@ export interface ComponentProps {
onSubmit: () => void;
submitButtonType?: undefined | ButtonStyleType;
isLoading?: boolean;
error?: string | undefined;
error?: string | undefined;
}
const ConfirmModal: FunctionComponent<ComponentProps> = (
@@ -32,7 +32,6 @@ const ConfirmModal: FunctionComponent<ComponentProps> = (
}
error={props.error}
>
<div>{props.description}</div>
</Modal>
);

View File

@@ -37,7 +37,9 @@ const Modal: FunctionComponent<ComponentProps> = (
props.onClose ? props.onClose : undefined
}
/>
<ModalBody error={props.error}>{props.children}</ModalBody>
<ModalBody error={props.error}>
{props.children}
</ModalBody>
<ModalFooter
submitButtonType={
props.submitButtonType

View File

@@ -9,15 +9,14 @@ export interface ComponentProps {
const ModalBody: FunctionComponent<ComponentProps> = (
props: ComponentProps
): ReactElement => {
return <div className="modal-body">
{props.error && (
<Alert
title={props.error}
type={AlertType.DANGER}
/>
)}
{props.children}
</div>;
return (
<div className="modal-body">
{props.error && (
<Alert title={props.error} type={AlertType.DANGER} />
)}
{props.children}
</div>
);
};
export default ModalBody;

View File

@@ -19,7 +19,7 @@ import Detail from '../Detail/Detail';
import Populate from '../../Utils/ModelAPI/Populate';
export interface ComponentProps<TBaseModel extends BaseModel> {
modelType: { new(): TBaseModel };
modelType: { new (): TBaseModel };
id: string;
fields: Array<Field<TBaseModel>>;
onLoadingChange?: undefined | ((isLoading: boolean) => void);
@@ -71,16 +71,14 @@ const ModelDetail: Function = <TBaseModel extends BaseModel>(
? (Object.keys(field.field)[0] as string)
: null;
if (key && model.isFileColumn(key)) {
(populate as JSONObject)[key] = {
file: true,
_id: true,
file: true,
_id: true,
type: true,
name: true
name: true,
};
} else if (key && model.isEntityColumn(key)) {
(populate as JSONObject)[key] = (field.field as any)[key];
}
}
@@ -138,12 +136,12 @@ const ModelDetail: Function = <TBaseModel extends BaseModel>(
...field,
getElement: field.getElement
? (item: JSONObject): ReactElement => {
return field.getElement!(
item,
onBeforeFetchData,
fetchItem
);
}
return field.getElement!(
item,
onBeforeFetchData,
fetchItem
);
}
: undefined,
});
}
@@ -152,12 +150,12 @@ const ModelDetail: Function = <TBaseModel extends BaseModel>(
...field,
getElement: field.getElement
? (item: JSONObject): ReactElement => {
return field.getElement!(
item,
onBeforeFetchData,
fetchItem
);
}
return field.getElement!(
item,
onBeforeFetchData,
fetchItem
);
}
: undefined,
});
}

View File

@@ -429,10 +429,9 @@ const ModelTable: Function = <TBaseModel extends BaseModel>(
file: true,
_id: true,
type: true,
name: true
name: true,
};
} else if (key && model.isEntityColumn(key)) {
(populate as JSONObject)[key] = (column.field as any)[key];
}
}
@@ -708,7 +707,8 @@ const ModelTable: Function = <TBaseModel extends BaseModel>(
if (props.onBeforeView) {
item = BaseModel.toJSONObject(
await props.onBeforeView(baseModel), props.modelType
await props.onBeforeView(baseModel),
props.modelType
);
}
@@ -766,8 +766,9 @@ const ModelTable: Function = <TBaseModel extends BaseModel>(
item,
props.modelType
)
), props.modelType
)
),
props.modelType
);
}
setModalType(ModalType.Edit);
@@ -803,8 +804,9 @@ const ModelTable: Function = <TBaseModel extends BaseModel>(
item,
props.modelType
)
), props.modelType
)
),
props.modelType
);
}
setShowDeleteConfirmModal(true);

View File

@@ -67,12 +67,10 @@ const Item: FunctionComponent<ComponentProps> = (
<div className="margin-10">
{props.actionButtons?.map(
(button: ActionButtonSchema, i: number) => {
if (button.isVisible && !button.isVisible(props.item)) {
return <></>
return <></>;
}
return (
<span
style={

View File

@@ -105,9 +105,11 @@ const TableRow: FunctionComponent<ComponentProps> = (
button: ActionButtonSchema,
i: number
) => {
if (button.isVisible && !button.isVisible(props.item)) {
return <></>
if (
button.isVisible &&
!button.isVisible(props.item)
) {
return <></>;
}
return (

View File

@@ -113,7 +113,7 @@ export default class ModelAPI {
formType: FormType,
apiUrlOverride?: URL,
miscDataProps?: JSONObject,
requestOptions?: RequestOptions | undefined,
requestOptions?: RequestOptions | undefined
): Promise<
HTTPResponse<JSONObject | JSONArray | TBaseModel | Array<TBaseModel>>
> {
@@ -145,7 +145,9 @@ export default class ModelAPI {
httpMethod,
apiUrl,
{
data: JSONFunctions.serialize(BaseModel.toJSON(model, modelType)),
data: JSONFunctions.serialize(
BaseModel.toJSON(model, modelType)
),
miscDataProps: miscDataProps || {},
},
this.getCommonHeaders(requestOptions)

View File

@@ -26,7 +26,6 @@ import StatusPagesViewAdvancedOptions from './Pages/StatusPages/View/AdvancedOpt
import StatusPagesViewCustomHtmlCss from './Pages/StatusPages/View/CustomHtmlCss';
import StatusPagesViewGroups from './Pages/StatusPages/View/Groups';
import Incidents from './Pages/Incidents/Incidents';
import IncidentView from './Pages/Incidents/View/Index';
import IncidentViewDelete from './Pages/Incidents/View/Delete';
@@ -124,7 +123,7 @@ const App: FunctionComponent = () => {
} catch (err) {
setError(
(err as HTTPErrorResponse).message ||
'Server Error. Please try again'
'Server Error. Please try again'
);
}
@@ -206,7 +205,7 @@ const App: FunctionComponent = () => {
<MonitorViewStatusTimeline
pageRoute={
RouteMap[
PageMap.MONITOR_VIEW_STATUS_TIMELINE
PageMap.MONITOR_VIEW_STATUS_TIMELINE
] as Route
}
currentProject={selectedProject}
@@ -220,7 +219,7 @@ const App: FunctionComponent = () => {
<MonitorIncidents
pageRoute={
RouteMap[
PageMap.MONITOR_VIEW_INCIDENTS
PageMap.MONITOR_VIEW_INCIDENTS
] as Route
}
currentProject={selectedProject}
@@ -258,7 +257,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewDelete
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_DELETE
PageMap.STATUS_PAGE_VIEW_DELETE
] as Route
}
currentProject={selectedProject}
@@ -274,7 +273,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewBranding
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_BRANDING
PageMap.STATUS_PAGE_VIEW_BRANDING
] as Route
}
currentProject={selectedProject}
@@ -290,7 +289,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewCustomHtmlCss
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_CUSTOM_HTML_CSS
PageMap.STATUS_PAGE_VIEW_CUSTOM_HTML_CSS
] as Route
}
currentProject={selectedProject}
@@ -306,7 +305,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewAdvancedOptions
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_ADVANCED_OPTIONS
PageMap.STATUS_PAGE_VIEW_ADVANCED_OPTIONS
] as Route
}
currentProject={selectedProject}
@@ -322,7 +321,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewSubscribers
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_SUBSCRIBERS
PageMap.STATUS_PAGE_VIEW_SUBSCRIBERS
] as Route
}
currentProject={selectedProject}
@@ -338,7 +337,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewEmbedded
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_EMBEDDED
PageMap.STATUS_PAGE_VIEW_EMBEDDED
] as Route
}
currentProject={selectedProject}
@@ -354,7 +353,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewResources
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_RESOURCES
PageMap.STATUS_PAGE_VIEW_RESOURCES
] as Route
}
currentProject={selectedProject}
@@ -370,7 +369,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewDomains
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_DOMAINS
PageMap.STATUS_PAGE_VIEW_DOMAINS
] as Route
}
currentProject={selectedProject}
@@ -379,14 +378,12 @@ const App: FunctionComponent = () => {
/>
<PageRoute
path={RouteMap[
PageMap.STATUS_PAGE_VIEW_GROUPS
]?.toString()}
path={RouteMap[PageMap.STATUS_PAGE_VIEW_GROUPS]?.toString()}
element={
<StatusPagesViewGroups
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_GROUPS
PageMap.STATUS_PAGE_VIEW_GROUPS
] as Route
}
currentProject={selectedProject}
@@ -402,7 +399,7 @@ const App: FunctionComponent = () => {
<StatusPagesViewAnnouncement
pageRoute={
RouteMap[
PageMap.STATUS_PAGE_VIEW_ANNOUNCEMENTS
PageMap.STATUS_PAGE_VIEW_ANNOUNCEMENTS
] as Route
}
currentProject={selectedProject}
@@ -452,7 +449,7 @@ const App: FunctionComponent = () => {
<IncidentViewStateTimeline
pageRoute={
RouteMap[
PageMap.INCIDENT_VIEW_STATE_TIMELINE
PageMap.INCIDENT_VIEW_STATE_TIMELINE
] as Route
}
currentProject={selectedProject}
@@ -466,7 +463,7 @@ const App: FunctionComponent = () => {
<IncidentInternalNote
pageRoute={
RouteMap[
PageMap.INCIDENT_INTERNAL_NOTE
PageMap.INCIDENT_INTERNAL_NOTE
] as Route
}
currentProject={selectedProject}
@@ -530,7 +527,7 @@ const App: FunctionComponent = () => {
<SettingsMonitors
pageRoute={
RouteMap[
PageMap.SETTINGS_MONITORS_STATUS
PageMap.SETTINGS_MONITORS_STATUS
] as Route
}
currentProject={selectedProject}
@@ -546,23 +543,7 @@ const App: FunctionComponent = () => {
<SettingsIncidents
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENTS_STATE
] as Route
}
currentProject={selectedProject}
/>
}
/>
<PageRoute
path={RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
]?.toString()}
element={
<SettingsIncidentSeverity
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
PageMap.SETTINGS_INCIDENTS_STATE
] as Route
}
currentProject={selectedProject}
@@ -572,14 +553,26 @@ const App: FunctionComponent = () => {
<PageRoute
path={RouteMap[
PageMap.SETTINGS_DOMAINS
PageMap.SETTINGS_INCIDENTS_SEVERITY
]?.toString()}
element={
<SettingsIncidentSeverity
pageRoute={
RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
] as Route
}
currentProject={selectedProject}
/>
}
/>
<PageRoute
path={RouteMap[PageMap.SETTINGS_DOMAINS]?.toString()}
element={
<SettingsDomains
pageRoute={
RouteMap[
PageMap.SETTINGS_DOMAINS
] as Route
RouteMap[PageMap.SETTINGS_DOMAINS] as Route
}
currentProject={selectedProject}
/>

View File

@@ -149,7 +149,7 @@ const ActiveIncidentsModal: FunctionComponent<ComponentProps> = (
field: {
incidentSeverity: {
name: true,
color: true,
color: true,
},
},
title: 'Incident Severity',

View File

@@ -152,7 +152,10 @@ const ChangeIncidentState: FunctionComponent<ComponentProps> = (
incidentStateTimeline.incidentId = props.incidentId;
incidentStateTimeline.incidentStateId = stateId;
await ModelAPI.create(incidentStateTimeline, IncidentStateTimeline);
await ModelAPI.create(
incidentStateTimeline,
IncidentStateTimeline
);
props.onActionComplete();
setIsLaoding(false);

View File

@@ -78,8 +78,7 @@ const IncidentsPage: FunctionComponent<PageComponentProps> = (
incidentSeverity: true,
},
title: 'Incident Severity',
description:
'What type of incident is this?',
description: 'What type of incident is this?',
fieldType: FormFieldSchemaType.Dropdown,
dropdownModal: {
type: IncidentSeverity,

View File

@@ -1,6 +1,11 @@
import Route from 'Common/Types/API/Route';
import Page from 'CommonUI/src/Components/Page/Page';
import React, { FunctionComponent, ReactElement, useEffect, useState } from 'react';
import React, {
FunctionComponent,
ReactElement,
useEffect,
useState,
} from 'react';
import PageMap from '../../Utils/PageMap';
import RouteMap from '../../Utils/RouteMap';
import PageComponentProps from '../PageComponentProps';
@@ -9,7 +14,7 @@ import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
import FieldType from 'CommonUI/src/Components/Types/FieldType';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import { IconProp } from 'CommonUI/src/Components/Icon/Icon';
import Domain from "Model/Models/Domain";
import Domain from 'Model/Models/Domain';
import { ButtonStyleType } from 'CommonUI/src/Components/Button/Button';
import { JSONObject } from 'Common/Types/JSON';
import ModelAPI from 'CommonUI/src/Utils/ModelAPI/ModelAPI';
@@ -20,12 +25,14 @@ import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse';
const Domains: FunctionComponent<PageComponentProps> = (
props: PageComponentProps
): ReactElement => {
const [showVerificationModal, setShowVerificationModal] = useState<boolean>(false);
const [showVerificationModal, setShowVerificationModal] =
useState<boolean>(false);
const [error, setError] = useState<string>('');
const [currentVerificationDomain, setCurrentVerificationDomain] = useState<JSONObject | null>(null);
const [currentVerificationDomain, setCurrentVerificationDomain] =
useState<JSONObject | null>(null);
const [refreshToggle, setRefreshToggle] = useState<boolean>(false);
const [isVerificationLoading, setIsVerificationLoading] = useState<boolean>(false);
const [isVerificationLoading, setIsVerificationLoading] =
useState<boolean>(false);
useEffect(() => {
setError('');
@@ -86,15 +93,11 @@ const Domains: FunctionComponent<PageComponentProps> = (
onError: (err: Error) => void
) => {
try {
setCurrentVerificationDomain(item);
setShowVerificationModal(true);
onCompleteAction();
} catch (err) {
onCompleteAction();
onError(err as Error);
}
@@ -113,10 +116,10 @@ const Domains: FunctionComponent<PageComponentProps> = (
validation: {
minLength: 2,
},
}
},
]}
selectMoreFields={{
domainVerificationText: true
domainVerificationText: true,
}}
showRefreshButton={true}
showFilterButton={true}
@@ -144,39 +147,62 @@ const Domains: FunctionComponent<PageComponentProps> = (
title={`Verify ${currentVerificationDomain['domain']}`}
error={error}
description={
(<div>
<span>Please add TXT record to your domain. Details of the TXT records are:</span>
<div>
<span>
Please add TXT record to your domain. Details of
the TXT records are:
</span>
<br />
<br />
<span><b>Record Type: </b> TXT</span><br />
<span><b>Name: </b> @ or {currentVerificationDomain['domain']?.toString()}</span><br />
<span><b>Content: </b>{currentVerificationDomain['domainVerificationText'] as string || ''}</span><br />
<span>
<b>Record Type: </b> TXT
</span>
<br />
<span>Please note: Some domain changes might take 72 hours to propogate.</span>
</div>)
}
<span>
<b>Name: </b> @ or{' '}
{currentVerificationDomain[
'domain'
]?.toString()}
</span>
<br />
<span>
<b>Content: </b>
{(currentVerificationDomain[
'domainVerificationText'
] as string) || ''}
</span>
<br />
<br />
<span>
Please note: Some domain changes might take 72
hours to propogate.
</span>
</div>
}
submitButtonText={'Verify Domain'}
onClose={() => {
setShowVerificationModal(false)
setShowVerificationModal(false);
setError('');
}}
isLoading={isVerificationLoading}
onSubmit={async () => {
try {
setIsVerificationLoading(true)
setIsVerificationLoading(true);
setError('');
// verify domain.
await ModelAPI.updateById(
Domain,
new ObjectID(
currentVerificationDomain['_id']
? currentVerificationDomain['_id'].toString()
? currentVerificationDomain[
'_id'
].toString()
: ''
),
{
isVerified: true,
},
undefined,
undefined
);
setIsVerificationLoading(false);
setShowVerificationModal(false);
@@ -192,10 +218,11 @@ const Domains: FunctionComponent<PageComponentProps> = (
}
setIsVerificationLoading(false);
}
}}
/>
) : <></>}
) : (
<></>
)}
</Page>
);
};

View File

@@ -78,7 +78,9 @@ const DashboardSideMenu: FunctionComponent = (): ReactElement => {
link={{
title: 'Incident Severity',
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS_INCIDENTS_SEVERITY] as Route
RouteMap[
PageMap.SETTINGS_INCIDENTS_SEVERITY
] as Route
),
}}
icon={IconProp.Alert}

View File

@@ -153,7 +153,7 @@ const StatusPageDelete: FunctionComponent<PageComponentProps> = (
field: {
logoFile: {
file: true,
type: true
type: true,
},
},
fieldType: FieldType.ImageFile,
@@ -164,7 +164,7 @@ const StatusPageDelete: FunctionComponent<PageComponentProps> = (
field: {
coverImageFile: {
file: true,
type: true
type: true,
},
},
fieldType: FieldType.ImageFile,
@@ -175,7 +175,7 @@ const StatusPageDelete: FunctionComponent<PageComponentProps> = (
field: {
faviconFile: {
file: true,
type: true
type: true,
},
},
fieldType: FieldType.ImageFile,

View File

@@ -122,21 +122,17 @@ const DashboardSideMenu: FunctionComponent<ComponentProps> = (
</SideMenuSection>
<SideMenuSection title="Advanced">
<SideMenuItem
<SideMenuItem
link={{
title: 'Groups',
to: RouteUtil.populateRouteParams(
RouteMap[
PageMap.STATUS_PAGE_VIEW_GROUPS
] as Route,
RouteMap[PageMap.STATUS_PAGE_VIEW_GROUPS] as Route,
props.modelId
),
}}
icon={IconProp.Folder}
/>
<SideMenuItem
link={{
title: 'Advanced Options',

View File

@@ -8,7 +8,6 @@ enum PageMap {
INCIDENT_VIEW_STATE_TIMELINE = 'INCIDENT_VIEW_STATE_TIMELINE',
INCIDENT_INTERNAL_NOTE = 'INCIDENT_INTERNAL_NOTE',
INCIDENT_PUBLIC_NOTE = 'INCIDENT_PUBLIC_NOTE',
MONITORS = 'MONITORS',
MONITOR_VIEW = 'MONITOR_VIEW',
@@ -29,7 +28,6 @@ enum PageMap {
STATUS_PAGE_VIEW_CUSTOM_HTML_CSS = 'STATUS_PAGE_VIEW_CUSTOM_HTML_CSS',
STATUS_PAGE_VIEW_GROUPS = 'STATUS_PAGE_VIEW_GROUPS',
LOGS = 'LOGS',
ON_CALL_DUTY = 'ON_CALL_DUTY',
AUTOMATION_SCRIPTS = 'AUTOMATION_SCRIPTS',

View File

@@ -50,7 +50,6 @@ const RouteMap: Dictionary<Route> = {
`/dashboard/${RouteParams.ProjectID}/status-pages/${RouteParams.ModelID}/branding`
),
[PageMap.STATUS_PAGE_VIEW_GROUPS]: new Route(
`/dashboard/${RouteParams.ProjectID}/status-pages/${RouteParams.ModelID}/groups`
),

View File

@@ -116,7 +116,6 @@ import DomainService, {
Service as DomainServiceType,
} from 'CommonServer/Services/DomainService';
import StatusPageGroup from 'Model/Models/StatusPageGroup';
import StatusPageGroupService, {
Service as StatusPageGroupServiceType,
@@ -127,7 +126,6 @@ import StatusPageResourceService, {
Service as StatusPageResourceServiceType,
} from 'CommonServer/Services/StatusPageResourceService';
import IncidentSeverity from 'Model/Models/IncidentSeverity';
import IncidentSeverityService, {
Service as IncidentSeverityServiceType,
@@ -190,10 +188,7 @@ app.use(
);
app.use(
new BaseAPI<Domain, DomainServiceType>(
Domain,
DomainService
).getRouter()
new BaseAPI<Domain, DomainServiceType>(Domain, DomainService).getRouter()
);
app.use(
@@ -210,7 +205,6 @@ app.use(
).getRouter()
);
app.use(
new BaseAPI<IncidentStateTimeline, IncidentStateTimelineServiceType>(
IncidentStateTimeline,
@@ -236,7 +230,10 @@ app.use(
);
app.use(
new BaseAPI<IncidentSeverity, IncidentSeverityServiceType>(IncidentSeverity, IncidentSeverityService).getRouter()
new BaseAPI<IncidentSeverity, IncidentSeverityServiceType>(
IncidentSeverity,
IncidentSeverityService
).getRouter()
);
app.use(new BaseAPI<Label, LabelServiceType>(Label, LabelService).getRouter());

View File

@@ -157,10 +157,15 @@ router.post(
OneUptimeDate.getSecondsInDays(new PositiveNumber(30))
);
return Response.sendItemResponse(req, res, {
token: token,
user: BaseModel.toJSON(savedUser, User),
}, User);
return Response.sendItemResponse(
req,
res,
{
token: token,
user: BaseModel.toJSON(savedUser, User),
},
User
);
}
throw new BadRequestException('Failed to create a user');
@@ -204,10 +209,15 @@ router.post(
OneUptimeDate.getSecondsInDays(new PositiveNumber(30))
);
return Response.sendItemResponse(req, res, {
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
}, User);
return Response.sendItemResponse(
req,
res,
{
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
},
User
);
}
throw new BadDataException(
'Invalid login: Email or password does not match.'
@@ -251,10 +261,15 @@ router.post(
OneUptimeDate.getSecondsInDays(new PositiveNumber(30))
);
return Response.sendItemResponse(req, res, {
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
}, User);
return Response.sendItemResponse(
req,
res,
{
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
},
User
);
}
throw new BadDataException(
'Invalid login: Email or password does not match.'
@@ -299,10 +314,15 @@ router.post(
OneUptimeDate.getSecondsInDays(new PositiveNumber(30))
);
return Response.sendItemResponse(req, res, {
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
}, User);
return Response.sendItemResponse(
req,
res,
{
token: token,
user: BaseModel.toJSON(alreadySavedUser, User),
},
User
);
}
throw new BadDataException(
'Invalid login: Email or password does not match.'

View File

@@ -16,7 +16,7 @@ import ColumnAccessControl from 'Common/Types/Database/AccessControl/ColumnAcces
import UniqueColumnBy from 'Common/Types/Database/UniqueColumnBy';
import TenantColumn from 'Common/Types/Database/TenantColumn';
import SingularPluralName from 'Common/Types/Database/SingularPluralName';
import DomainType from "Common/Types/Domain";
import DomainType from 'Common/Types/Domain';
@TenantColumn('projectId')
@TableAccessControl({
@@ -118,8 +118,6 @@ export default class Domain extends BaseModel {
})
public slug?: string = undefined;
@ColumnAccessControl({
create: [Permission.ProjectOwner, Permission.CanCreateProjectDomain],
read: [
@@ -226,7 +224,6 @@ export default class Domain extends BaseModel {
})
public isVerified?: boolean = undefined;
@ColumnAccessControl({
create: [],
read: [

View File

@@ -344,8 +344,6 @@ export default class Incident extends BaseModel {
})
public currentIncidentStateId?: ObjectID = undefined;
@ColumnAccessControl({
create: [Permission.ProjectOwner, Permission.CanCreateProjectIncident],
read: [
@@ -391,7 +389,6 @@ export default class Incident extends BaseModel {
})
public incidentSeverityId?: ObjectID = undefined;
@ColumnAccessControl({
create: [Permission.ProjectOwner, Permission.CanCreateProjectIncident],
read: [

View File

@@ -37,10 +37,7 @@ import SingularPluralName from 'Common/Types/Database/SingularPluralName';
})
export default class IncidentSeverity extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
@@ -68,10 +65,7 @@ export default class IncidentSeverity extends BaseModel {
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
@@ -89,19 +83,13 @@ export default class IncidentSeverity extends BaseModel {
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditIncidentSeverity,
],
update: [Permission.ProjectOwner, Permission.CanEditIncidentSeverity],
})
@TableColumn({ required: true, type: TableColumnType.ShortText })
@Column({
@@ -130,19 +118,13 @@ export default class IncidentSeverity extends BaseModel {
public slug?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditIncidentSeverity,
],
update: [Permission.ProjectOwner, Permission.CanEditIncidentSeverity],
})
@TableColumn({ required: false, type: TableColumnType.LongText })
@Column({
@@ -153,10 +135,7 @@ export default class IncidentSeverity extends BaseModel {
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
@@ -184,10 +163,7 @@ export default class IncidentSeverity extends BaseModel {
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
@@ -249,19 +225,13 @@ export default class IncidentSeverity extends BaseModel {
public deletedByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditIncidentSeverity,
],
update: [Permission.ProjectOwner, Permission.CanEditIncidentSeverity],
})
@TableColumn({
title: 'Color',
@@ -278,22 +248,15 @@ export default class IncidentSeverity extends BaseModel {
})
public color?: Color = undefined;
@UniqueColumnBy('projectId')
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateIncidentSeverity,
],
create: [Permission.ProjectOwner, Permission.CanCreateIncidentSeverity],
read: [
Permission.ProjectOwner,
Permission.CanReadIncidentSeverity,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditIncidentSeverity,
],
update: [Permission.ProjectOwner, Permission.CanEditIncidentSeverity],
})
@TableColumn({
isDefaultValueColumn: false,

View File

@@ -19,7 +19,7 @@ import Label from './Label';
import StatusPage from './StatusPage';
import StatusPageGroup from './StatusPageGroup';
import StatusPageDomain from './StatusPageDomain';
import StatusPageResource from './StatusPageResource'
import StatusPageResource from './StatusPageResource';
// On Call Duty
import OnCallDuty from './OnCallDuty';
@@ -71,5 +71,5 @@ export default [
StatusPageGroup,
StatusPageDomain,
StatusPageResource,
IncidentSeverity
IncidentSeverity,
];

View File

@@ -38,10 +38,7 @@ import Domain from './Domain';
})
export default class StatusPageDomain extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -69,10 +66,7 @@ export default class StatusPageDomain extends BaseModel {
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -89,12 +83,8 @@ export default class StatusPageDomain extends BaseModel {
})
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -122,10 +112,7 @@ export default class StatusPageDomain extends BaseModel {
public domain?: Domain = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -142,13 +129,8 @@ export default class StatusPageDomain extends BaseModel {
})
public domainId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -176,10 +158,7 @@ export default class StatusPageDomain extends BaseModel {
public statusPage?: StatusPage = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -197,19 +176,13 @@ export default class StatusPageDomain extends BaseModel {
public statusPageId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageDomain,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageDomain],
})
@TableColumn({ required: true, type: TableColumnType.ShortText })
@Column({
@@ -220,17 +193,10 @@ export default class StatusPageDomain extends BaseModel {
@UniqueColumnBy('projectId')
public subdomain?: string = undefined;
@ColumnAccessControl({
create: [
],
read: [
],
update: [
],
create: [],
read: [],
update: [],
})
@TableColumn({ required: true, type: TableColumnType.ShortText })
@Column({
@@ -240,12 +206,8 @@ export default class StatusPageDomain extends BaseModel {
})
public fullDomain?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -273,10 +235,7 @@ export default class StatusPageDomain extends BaseModel {
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageDomain,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageDomain],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageDomain,
@@ -319,5 +278,4 @@ export default class StatusPageDomain extends BaseModel {
)
@JoinColumn({ name: 'deletedByUserId' })
public deletedByUser?: User = undefined;
}

View File

@@ -37,10 +37,7 @@ import StatusPage from './StatusPage';
})
export default class StatusPageGroup extends BaseModel {
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -68,10 +65,7 @@ export default class StatusPageGroup extends BaseModel {
public project?: Project = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -89,10 +83,7 @@ export default class StatusPageGroup extends BaseModel {
public projectId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -120,10 +111,7 @@ export default class StatusPageGroup extends BaseModel {
public statusPage?: StatusPage = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -141,19 +129,13 @@ export default class StatusPageGroup extends BaseModel {
public statusPageId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageGroup,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageGroup],
})
@TableColumn({ required: true, type: TableColumnType.ShortText })
@Column({
@@ -182,19 +164,13 @@ export default class StatusPageGroup extends BaseModel {
public slug?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageGroup,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageGroup],
})
@TableColumn({ required: false, type: TableColumnType.LongText })
@Column({
@@ -205,10 +181,7 @@ export default class StatusPageGroup extends BaseModel {
public description?: string = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -236,10 +209,7 @@ export default class StatusPageGroup extends BaseModel {
public createdByUser?: User = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
@@ -256,19 +226,13 @@ export default class StatusPageGroup extends BaseModel {
public createdByUserId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.CanCreateStatusPageGroup,
],
create: [Permission.ProjectOwner, Permission.CanCreateStatusPageGroup],
read: [
Permission.ProjectOwner,
Permission.CanReadStatusPageGroup,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageGroup,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageGroup],
})
@TableColumn({ isDefaultValueColumn: false, type: TableColumnType.Number })
@Column({

View File

@@ -141,8 +141,6 @@ export default class StatusPageResource extends BaseModel {
})
public statusPageId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
@@ -195,7 +193,6 @@ export default class StatusPageResource extends BaseModel {
})
public monitorId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
@@ -248,8 +245,6 @@ export default class StatusPageResource extends BaseModel {
})
public statusPageGroupId?: ObjectID = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
@@ -260,10 +255,7 @@ export default class StatusPageResource extends BaseModel {
Permission.CanReadStatusPageResource,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageResource,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageResource],
})
@TableColumn({ required: false, type: TableColumnType.LongText })
@Column({
@@ -334,10 +326,7 @@ export default class StatusPageResource extends BaseModel {
Permission.CanReadStatusPageResource,
Permission.ProjectMember,
],
update: [
Permission.ProjectOwner,
Permission.CanEditStatusPageResource,
],
update: [Permission.ProjectOwner, Permission.CanEditStatusPageResource],
})
@TableColumn({ isDefaultValueColumn: false, type: TableColumnType.Number })
@Column({