Add frontend, backend and CLI

This commit is contained in:
Maidul Islam
2022-11-17 17:54:35 -05:00
parent 8d00c5cdb7
commit bea0ff6e05
276 changed files with 50230 additions and 72 deletions
+56
View File
@@ -0,0 +1,56 @@
import { Schema, model, Types } from 'mongoose';
export interface IBackupPrivateKey {
_id: Types.ObjectId;
user: Types.ObjectId;
encryptedPrivateKey: string;
iv: string;
tag: string;
salt: string;
verifier: string;
}
const backupPrivateKeySchema = new Schema<IBackupPrivateKey>(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
encryptedPrivateKey: {
type: String,
select: false,
required: true
},
iv: {
type: String,
select: false,
required: true
},
tag: {
type: String,
select: false,
required: true
},
salt: {
type: String,
select: false,
required: true
},
verifier: {
type: String,
select: false,
required: true
}
},
{
timestamps: true
}
);
const BackupPrivateKey = model<IBackupPrivateKey>(
'BackupPrivateKey',
backupPrivateKeySchema
);
export default BackupPrivateKey;
+31
View File
@@ -0,0 +1,31 @@
import { Schema, model, Types } from 'mongoose';
export interface IIncidentContactOrg {
_id: Types.ObjectId;
email: string;
organization: Types.ObjectId;
}
const incidentContactOrgSchema = new Schema<IIncidentContactOrg>(
{
email: {
type: String,
required: true
},
organization: {
type: Schema.Types.ObjectId,
ref: 'Organization',
required: true
}
},
{
timestamps: true
}
);
const IncidentContactOrg = model<IIncidentContactOrg>(
'IncidentContactOrg',
incidentContactOrgSchema
);
export default IncidentContactOrg;
+45
View File
@@ -0,0 +1,45 @@
import BackupPrivateKey, { IBackupPrivateKey } from './backupPrivateKey';
import IncidentContactOrg, { IIncidentContactOrg } from './incidentContactOrg';
import Integration, { IIntegration } from './integration';
import IntegrationAuth, { IIntegrationAuth } from './integrationAuth';
import Key, { IKey } from './key';
import Membership, { IMembership } from './membership';
import MembershipOrg, { IMembershipOrg } from './membershipOrg';
import Organization, { IOrganization } from './organization';
import Secret, { ISecret } from './secret';
import ServiceToken, { IServiceToken } from './serviceToken';
import Token, { IToken } from './token';
import User, { IUser } from './user';
import UserAction, { IUserAction } from './userAction';
import Workspace, { IWorkspace } from './workspace';
export {
BackupPrivateKey,
IBackupPrivateKey,
IncidentContactOrg,
IIncidentContactOrg,
Integration,
IIntegration,
IntegrationAuth,
IIntegrationAuth,
Key,
IKey,
Membership,
IMembership,
MembershipOrg,
IMembershipOrg,
Organization,
IOrganization,
Secret,
ISecret,
ServiceToken,
IServiceToken,
Token,
IToken,
User,
IUser,
UserAction,
IUserAction,
Workspace,
IWorkspace
};
+61
View File
@@ -0,0 +1,61 @@
import { Schema, model, Types } from 'mongoose';
import {
ENV_DEV,
ENV_TESTING,
ENV_STAGING,
ENV_PROD,
INTEGRATION_HEROKU,
INTEGRATION_NETLIFY
} from '../variables';
export interface IIntegration {
_id: Types.ObjectId;
workspace: Types.ObjectId;
environment: 'dev' | 'test' | 'staging' | 'prod';
isActive: boolean;
app: string;
integration: 'heroku' | 'netlify';
integrationAuth: Types.ObjectId;
}
const integrationSchema = new Schema<IIntegration>(
{
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
},
environment: {
type: String,
enum: [ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD],
required: true
},
isActive: {
type: Boolean,
required: true
},
app: {
// name of app in provider
type: String,
default: null,
required: true
},
integration: {
type: String,
enum: [INTEGRATION_HEROKU, INTEGRATION_NETLIFY],
required: true
},
integrationAuth: {
type: Schema.Types.ObjectId,
ref: 'IntegrationAuth',
required: true
}
},
{
timestamps: true
}
);
const Integration = model<IIntegration>('Integration', integrationSchema);
export default Integration;
+67
View File
@@ -0,0 +1,67 @@
import { Schema, model, Types } from 'mongoose';
import { INTEGRATION_HEROKU, INTEGRATION_NETLIFY } from '../variables';
export interface IIntegrationAuth {
_id: Types.ObjectId;
workspace: Types.ObjectId;
integration: 'heroku' | 'netlify';
refreshCiphertext?: string;
refreshIV?: string;
refreshTag?: string;
accessCiphertext?: string;
accessIV?: string;
accessTag?: string;
accessExpiresAt?: Date;
}
const integrationAuthSchema = new Schema<IIntegrationAuth>(
{
workspace: {
type: Schema.Types.ObjectId,
required: true
},
integration: {
type: String,
enum: [INTEGRATION_HEROKU, INTEGRATION_NETLIFY],
required: true
},
refreshCiphertext: {
type: String,
select: false
},
refreshIV: {
type: String,
select: false
},
refreshTag: {
type: String,
select: false
},
accessCiphertext: {
type: String,
select: false
},
accessIV: {
type: String,
select: false
},
accessTag: {
type: String,
select: false
},
accessExpiresAt: {
type: Date,
select: false
}
},
{
timestamps: true
}
);
const IntegrationAuth = model<IIntegrationAuth>(
'IntegrationAuth',
integrationAuthSchema
);
export default IntegrationAuth;
+45
View File
@@ -0,0 +1,45 @@
import { Schema, model, Types } from 'mongoose';
export interface IKey {
_id: Types.ObjectId;
encryptedKey: string;
nonce: string;
sender: Types.ObjectId;
receiver: Types.ObjectId;
workspace: Types.ObjectId;
}
const keySchema = new Schema<IKey>(
{
encryptedKey: {
type: String,
required: true
},
nonce: {
type: String,
required: true
},
sender: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
receiver: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
}
},
{
timestamps: true
}
);
const Key = model<IKey>('Key', keySchema);
export default Key;
+46
View File
@@ -0,0 +1,46 @@
import { Schema, model, Types } from 'mongoose';
import { ADMIN, MEMBER, INVITED, COMPLETED, GRANTED } from '../variables';
export interface IMembership {
_id: Types.ObjectId;
user: Types.ObjectId;
inviteEmail?: string;
workspace: Types.ObjectId;
role: 'admin' | 'member';
status: 'invited' | 'completed' | 'granted';
}
const membershipSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
inviteEmail: {
type: String
},
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
},
role: {
type: String,
enum: [ADMIN, MEMBER],
required: true
},
status: {
// INVITED, COMPLETED, GRANTED
type: String,
enum: [INVITED, COMPLETED, GRANTED],
required: true
}
},
{
timestamps: true
}
);
const Membership = model<IMembership>('Membership', membershipSchema);
export default Membership;
+47
View File
@@ -0,0 +1,47 @@
import { Schema, model, Types } from 'mongoose';
import { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED } from '../variables';
export interface IMembershipOrg {
_id: Types.ObjectId;
user: Types.ObjectId;
inviteEmail: string;
organization: Types.ObjectId;
role: 'owner' | 'admin' | 'member';
status: 'invited' | 'accepted';
}
const membershipOrgSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
inviteEmail: {
type: String
},
organization: {
type: Schema.Types.ObjectId,
ref: 'Organization'
},
role: {
type: String,
enum: [OWNER, ADMIN, MEMBER],
required: true
},
status: {
type: String,
enum: [INVITED, ACCEPTED],
required: true
}
},
{
timestamps: true
}
);
const MembershipOrg = model<IMembershipOrg>(
'MembershipOrg',
membershipOrgSchema
);
export default MembershipOrg;
+26
View File
@@ -0,0 +1,26 @@
import { Schema, model, Types } from 'mongoose';
export interface IOrganization {
_id: Types.ObjectId;
name: string;
customerId?: string;
}
const organizationSchema = new Schema<IOrganization>(
{
name: {
type: String,
required: true
},
customerId: {
type: String
}
},
{
timestamps: true
}
);
const Organization = model<IOrganization>('Organization', organizationSchema);
export default Organization;
+89
View File
@@ -0,0 +1,89 @@
import { Schema, model, Types } from 'mongoose';
import {
SECRET_SHARED,
SECRET_PERSONAL,
ENV_DEV,
ENV_TESTING,
ENV_STAGING,
ENV_PROD
} from '../variables';
export interface ISecret {
_id: Types.ObjectId;
workspace: Types.ObjectId;
type: string;
user: Types.ObjectId;
environment: string;
secretKeyCiphertext: string;
secretKeyIV: string;
secretKeyTag: string;
secretKeyHash: string;
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
secretValueHash: string;
}
const secretSchema = new Schema<ISecret>(
{
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
},
type: {
type: String,
enum: [SECRET_SHARED, SECRET_PERSONAL],
required: true
},
user: {
// user associated with the personal secret
type: Schema.Types.ObjectId,
ref: 'User'
},
environment: {
type: String,
enum: [ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD],
required: true
},
secretKeyCiphertext: {
type: String,
required: true
},
secretKeyIV: {
type: String, // symmetric
required: true
},
secretKeyTag: {
type: String, // symmetric
required: true
},
secretKeyHash: {
type: String,
required: true
},
secretValueCiphertext: {
type: String,
required: true
},
secretValueIV: {
type: String, // symmetric
required: true
},
secretValueTag: {
type: String, // symmetric
required: true
},
secretValueHash: {
type: String,
required: true
}
},
{
timestamps: true
}
);
const Secret = model<ISecret>('Secret', secretSchema);
export default Secret;
+64
View File
@@ -0,0 +1,64 @@
import { Schema, model, Types } from 'mongoose';
import { ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD } from '../variables';
export interface IServiceToken {
_id: Types.ObjectId;
name: string;
user: Types.ObjectId;
workspace: Types.ObjectId;
environment: string;
expiresAt: Date;
publicKey: string;
encryptedKey: string;
nonce: string;
}
const serviceTokenSchema = new Schema<IServiceToken>(
{
name: {
type: String,
required: true
},
user: {
// token issuer
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
workspace: {
type: Schema.Types.ObjectId,
ref: 'Workspace',
required: true
},
environment: {
type: String,
enum: [ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD],
required: true
},
expiresAt: {
type: Date
},
publicKey: {
type: String,
required: true,
select: true
},
encryptedKey: {
type: String,
required: true,
select: true
},
nonce: {
type: String,
required: true,
select: true
}
},
{
timestamps: true
}
);
const ServiceToken = model<IServiceToken>('ServiceToken', serviceTokenSchema);
export default ServiceToken;
+28
View File
@@ -0,0 +1,28 @@
import { Schema, model } from 'mongoose';
import { EMAIL_TOKEN_LIFETIME } from '../config';
export interface IToken {
email: String;
token: String;
createdAt: Date;
}
const tokenSchema = new Schema<IToken>({
email: {
type: String,
required: true
},
token: {
type: String,
required: true
},
createdAt: {
type: Date,
expires: EMAIL_TOKEN_LIFETIME,
default: Date.now
}
});
const Token = model<IToken>('Token', tokenSchema);
export default Token;
+65
View File
@@ -0,0 +1,65 @@
import { Schema, model, Types } from 'mongoose';
export interface IUser {
_id: Types.ObjectId;
email: string;
firstName?: string;
lastName?: string;
publicKey?: string;
encryptedPrivateKey?: string;
iv?: string;
tag?: string;
salt?: string;
verifier?: string;
refreshVersion?: Number;
}
const userSchema = new Schema<IUser>(
{
email: {
type: String,
required: true
},
firstName: {
type: String
},
lastName: {
type: String
},
publicKey: {
type: String,
select: false
},
encryptedPrivateKey: {
type: String,
select: false
},
iv: {
type: String,
select: false
},
tag: {
type: String,
select: false
},
salt: {
type: String,
select: false
},
verifier: {
type: String,
select: false
},
refreshVersion: {
type: Number,
default: 0
}
},
{
timestamps: true
}
);
const User = model<IUser>('User', userSchema);
export default User;
+28
View File
@@ -0,0 +1,28 @@
import { Schema, model, Types } from 'mongoose';
export interface IUserAction {
_id: Types.ObjectId;
user: Types.ObjectId;
action: string;
}
const userActionSchema = new Schema<IUserAction>(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
action: {
type: String,
required: true
}
},
{
timestamps: true
}
);
const UserAction = model<IUserAction>('UserAction', userActionSchema);
export default UserAction;
+23
View File
@@ -0,0 +1,23 @@
import { Schema, model, Types } from 'mongoose';
export interface IWorkspace {
_id: Types.ObjectId;
name: string;
organization: Types.ObjectId;
}
const workspaceSchema = new Schema<IWorkspace>({
name: {
type: String,
required: true
},
organization: {
type: Schema.Types.ObjectId,
ref: 'Organization',
required: true
}
});
const Workspace = model<IWorkspace>('Workspace', workspaceSchema);
export default Workspace;