forked from cerc-io/snowballtools-base
Add checks for mutations and a mutation to add environment variables to project (#33)
* Add mutation to add environment variables by project id * Add checks while removing project members --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
58e20c15db
commit
02f7ebb9bd
@ -1,6 +1,7 @@
|
|||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
import { DatabaseConfig } from './config';
|
import { DatabaseConfig } from './config';
|
||||||
import { User } from './entity/User';
|
import { User } from './entity/User';
|
||||||
@ -133,6 +134,7 @@ export class Database {
|
|||||||
async removeProjectMemberByMemberId (memberId: string): Promise<boolean> {
|
async removeProjectMemberByMemberId (memberId: string): Promise<boolean> {
|
||||||
// TODO: Check if user is authorized to delete members
|
// TODO: Check if user is authorized to delete members
|
||||||
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
||||||
|
|
||||||
const deleted = await projectMemberRepository.delete(memberId);
|
const deleted = await projectMemberRepository.delete(memberId);
|
||||||
|
|
||||||
if (deleted.affected) {
|
if (deleted.affected) {
|
||||||
@ -141,4 +143,51 @@ export class Database {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async addEnvironmentVariablesByProjectId (projectId: string, environmentVariables: any[]): Promise<boolean> {
|
||||||
|
const environmentVariableRepository = this.dataSource.getRepository(EnvironmentVariable);
|
||||||
|
const projectRepository = this.dataSource.getRepository(Project);
|
||||||
|
|
||||||
|
const project = await projectRepository.findOneBy({
|
||||||
|
id: projectId
|
||||||
|
});
|
||||||
|
assert(project);
|
||||||
|
|
||||||
|
const environmentVariablesPromises = environmentVariables.map(async environmentVariable => {
|
||||||
|
const envVar = new EnvironmentVariable();
|
||||||
|
|
||||||
|
envVar.key = environmentVariable.key;
|
||||||
|
envVar.value = environmentVariable.value;
|
||||||
|
envVar.environments = environmentVariable.environments;
|
||||||
|
envVar.project = project;
|
||||||
|
|
||||||
|
return environmentVariableRepository.save(envVar);
|
||||||
|
});
|
||||||
|
|
||||||
|
const savedEnvironmentVariables = await Promise.all(environmentVariablesPromises);
|
||||||
|
return savedEnvironmentVariables.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProjectMemberByMemberId (memberId: string): Promise<ProjectMember> {
|
||||||
|
const projectMemberRepository = this.dataSource.getRepository(ProjectMember);
|
||||||
|
|
||||||
|
const projectMemberWithProject = await projectMemberRepository.find({
|
||||||
|
relations: {
|
||||||
|
project: {
|
||||||
|
owner: true
|
||||||
|
},
|
||||||
|
member: true
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
id: Number(memberId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (projectMemberWithProject.length === 0) {
|
||||||
|
throw new Error('Member does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
return projectMemberWithProject[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
import { Database } from './database';
|
import { Database } from './database';
|
||||||
import { deploymentToGqlType, projectMemberToGqlType, projectToGqlType, environmentVariableToGqlType } from './utils';
|
import { deploymentToGqlType, projectMemberToGqlType, projectToGqlType, environmentVariableToGqlType, isUserOwner } from './utils';
|
||||||
|
|
||||||
const log = debug('snowball:database');
|
const log = debug('snowball:database');
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ export const createResolvers = async (db: Database): Promise<any> => {
|
|||||||
const orgsWithProjectsPromises = organizations.map(async (org) => {
|
const orgsWithProjectsPromises = organizations.map(async (org) => {
|
||||||
const dbProjects = await db.getProjectsByOrganizationId(org.id);
|
const dbProjects = await db.getProjectsByOrganizationId(org.id);
|
||||||
|
|
||||||
const projectsWithPromises = dbProjects.map(async (dbProject) => {
|
const projectsPromises = dbProjects.map(async (dbProject) => {
|
||||||
const dbProjectMembers = await db.getProjectMembersByProjectId(dbProject.id);
|
const dbProjectMembers = await db.getProjectMembersByProjectId(dbProject.id);
|
||||||
const dbEnvironmentVariables = await db.getEnvironmentVariablesByProjectId(dbProject.id);
|
const dbEnvironmentVariables = await db.getEnvironmentVariablesByProjectId(dbProject.id);
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ export const createResolvers = async (db: Database): Promise<any> => {
|
|||||||
return projectToGqlType(dbProject, projectMembers, environmentVariables);
|
return projectToGqlType(dbProject, projectMembers, environmentVariables);
|
||||||
});
|
});
|
||||||
|
|
||||||
const projects = await Promise.all(projectsWithPromises);
|
const projects = await Promise.all(projectsPromises);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...org,
|
...org,
|
||||||
@ -69,11 +70,33 @@ export const createResolvers = async (db: Database): Promise<any> => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Mutation: {
|
Mutation: {
|
||||||
removeMember: async (_: any, { memberId }:{ memberId: string }) => {
|
removeMember: async (_: any, { memberId }: { memberId: string }, context: any) => {
|
||||||
try {
|
try {
|
||||||
return await db.removeProjectMemberByMemberId(memberId);
|
const member = await db.getProjectMemberByMemberId(memberId);
|
||||||
} catch (error) {
|
|
||||||
log(error);
|
if (member.member.id === context.userId) {
|
||||||
|
throw new Error('Invalid operation: cannot remove self');
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberProject = member.project;
|
||||||
|
assert(memberProject);
|
||||||
|
|
||||||
|
if (isUserOwner(String(context.userId), String(memberProject.owner.id))) {
|
||||||
|
return db.removeProjectMemberByMemberId(memberId);
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid operation: not authorized');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
log(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addEnvironmentVariables: async (_: any, { projectId, environmentVariables }: { projectId: string, environmentVariables: { environments: string[], key: string, value: string}[] }) => {
|
||||||
|
try {
|
||||||
|
return db.addEnvironmentVariablesByProjectId(projectId, environmentVariables);
|
||||||
|
} catch (err) {
|
||||||
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,4 +120,11 @@ type Query {
|
|||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
removeMember(memberId: String!): Boolean!
|
removeMember(memberId: String!): Boolean!
|
||||||
|
addEnvironmentVariables(projectId: String!, environmentVariables: [AddEnvironmentVariableInput!]): Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
input AddEnvironmentVariableInput {
|
||||||
|
environments: [Environment!]!
|
||||||
|
key: String!
|
||||||
|
value: String!
|
||||||
}
|
}
|
||||||
|
@ -79,3 +79,7 @@ export const environmentVariableToGqlType = (dbEnvironmentVariable: EnvironmentV
|
|||||||
updatedAt: dbEnvironmentVariable.updatedAt
|
updatedAt: dbEnvironmentVariable.updatedAt
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isUserOwner = (userId: string, projectOwnerId: string): boolean => {
|
||||||
|
return userId === projectOwnerId;
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user