Razorpay | Machine Coding Round | Document Service Design
Anonymous User
4491

The problem was:
Design and implement a Simple document Service where users can create documents and read the same.
A document has a name and associated string content. Document=> <name{string}, content{string}>

All documents are private when created.
Owners of documents can {grant} {read OR edit} access to other users
Only the owner can delete a document
Username will be just a string. Every action like create/read/edit/delete must be made on behalf of a user

The interview was for 1 hr 30 min. It took 10-15 mins for introduction and explaining the problem. I had about 1 hr and 15 minutes to design and code. I am sharing the code that I wrote. I used typescript because I was not much confident in c++ (that is what I use for DSA). Please suggest what all could I have done better.

The user class:

import { AccessLevels } from "./accessLevels";
import Document from "./document";

export default class User {
    private id: number;
    private name: string;

    private documents: Document[];
    public static totalUser: number;
    constructor(name: string) {
        this.documents = [];
        this.name = name;
        this.id = ++User.totalUser;
    }

    public getId() {
        return this.id;
    }
    public createDocument(docName: string) {
        const doc: Document = new Document(docName, this.id);
        this.documents.push(doc);
    }

    public grantEditAccess(userId: number, docId: number) {
        for(const doc of this.documents) {
            if(doc.getId() == docId) {
                doc.setUserIdAccess(userId, AccessLevels.EDITOR);
                console.log('Editor Access granted to user: ', userId);
                return;
            }
        }
        console.log('The doc you are searching is not available');
    }

    public grantReadAccess(userId: number, docId: number) {
        for(const doc of this.documents) {
            if(doc.getId() == docId) {
                doc.setUserIdAccess(userId, AccessLevels.READER);
                console.log('Reader Access granted to user: ', userId);
                return;
            }
        }
        console.log('The doc you are searching is not available');
    }

    public getAllDocuments() {
        return this.documents;
    }
}

User.totalUser = 0;

The document class:

import { AccessLevels } from "./accessLevels";

export default class Document {
    private id: number;
    private name: string;
    private content: string;

    public userIdtoAccess: Map<number, AccessLevels>;

    public static totalDocs: number;

    constructor(name: string, userId: number) {
        Document.totalDocs++;
        this.name = name;
        this.id = Document.totalDocs; 
        this.content = '';
        this.userIdtoAccess  = new Map();
        this.userIdtoAccess[userId] = AccessLevels.OWNER;
    }

    public getId() {
        return this.id;
    }

    public getName() {
        return this.name
    }
 
    public getContent(userId: number) {
        const userAccess: AccessLevels = this.userIdtoAccess[userId];
        const readableAccess: AccessLevels[] = [AccessLevels.OWNER, AccessLevels.READER, AccessLevels.EDITOR];
        if(readableAccess.indexOf(userAccess) > -1) {
            return this.content;
        }
        return 'You are not authorised to access this document';
    }

    public setContent(content: string, userId: number) {
        const userAccess: AccessLevels = this.userIdtoAccess[userId];
        if(userAccess != AccessLevels.OWNER && userAccess != AccessLevels.EDITOR) {
            console.log('Sorry! you are not allowed to access this.');
            return;
        }
        this.content = content;
    }

    public getAllUsers() {
        return this.userIdtoAccess;
    }

    public getUserIdAccess(userId: number) {
        return this.userIdtoAccess[userId];
    }

    public setUserIdAccess(userId: number, access: AccessLevels) {
        this.userIdtoAccess[userId] = access;
    }
}
Document.totalDocs = 0;

Access level class:

export {
    AccessLevels
}
enum AccessLevels {
    OWNER,
    EDITOR,
    READER
}

Main function to test some cases

import Document from './models/document';
import User from './models/user';

main()

function main() {

    const user1: User = new User('Shyam');
    const user2: User = new User('Ram');
    user1.createDocument('myfirstDoc');
    user1.createDocument('mysecondDoc')

    const documents: Document[] = user1.getAllDocuments();
    const doc1: Document = documents[0];
    const doc2: Document = documents[1];
    doc1.setContent('My first line in the document', user1.getId());

    doc2.setContent('My first line in the second document', user2.getId());

   
    console.log(doc1.getContent(user1.getId()));
    console.log(doc2.getContent(user2.getId()));

    console.log('Adding access for the user2')
    user1.grantReadAccess(user2.getId(), doc1.getId());


    console.log(doc1.getContent(user2.getId()));
}
Comments (6)