npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@nasriya/mongodb

v1.0.6

Published

A MongoDB client with Schema & Authorization support.

Downloads

3

Readme

N|Solid

MongoDB.

Static Badge Repository Size Last Commit Status

Visit us at www.nasriya.net.

A MongoDB client with schemas, data-hooks, permissions, and more.

Made with ❤️ in Palestine 🇵🇸

[!IMPORTANT] 🌟 Support Our Open-Source Development! 🌟 We need your support to keep our projects going! If you find our > work valuable, please consider contributing. Your support helps us > continue to develop and maintain these tools.

Click here to support us!

Every contribution, big or small, makes a difference. Thank you for > your generosity and support!


Quick Start Guide

Installation

npm i @nasriya/mongodb

Importing

To use the cron scheduler, you must first import the cron-manager instance: Import in ESM modules:

import mongodb from '@nasriya/mongodb';

Import in CommonJS (CJS)

const mongodb = require('@nasriya/mongodb').default;

Preparing the Environment

Defining Databases

Our MongoDB client allows you define your databases and their collections, let's define one or two:

mongodb.defineDatabase({
    name: 'Auth',
    collections: [{ name: 'Passwords' }, { name: 'AuthHistory' }]
})

In our example above, we defined a database Auth with two collections, Passwords and AuthHistory. But, we do more than just that, let's imporove our DB definition with the following additions.

Collection Schemas

We can improve the collection definition and validation by defining Schemas for our collections. To do that, we'll use the schema() method on the adapter to create and validate our schema object. While you can directly pass the schema object to the collection definition, it's recommended to use the schema() method for easier debugging if anything went wrong.

const pswdsSchema = mongodb.schema({
    hashed: {
        type: 'String',
        required: true,
        validity: {
            message: 'The hashed value you passed is invalid',
            handler: (value): boolean => {
                if (typeof value === 'string' && (value.length >=10 && value.length <= 32)) {
                    return true;
                } else {
                    return false;
                }                
            }
        }
    },
    expireAfter: {
        type: 'Number',
        default: 2.592e+9 // 30 days
    }
})

In our example above, we defined the hashed property as a String and set it as a required field when inserting new data. We've also set a validity handler and a validity message that will be thrown if the handler returned false, indicating that the value is invalid.

We also defined the expireAfter property as a Number, and set a default value of 30 days in case the user didn't provide one.

That's how the DB definition becomes:

mongodb.defineDatabase({
    name: 'Auth',
    collections: [{ 
        name: 'Passwords',
        schema: pswdsSchema
    }]
})
Collection Permissions

You can also set the IO permissions on each collection based on user authorizations.

mongodb.defineDatabase({
    name: 'Auth',
    collections: [{ 
        name: 'Passwords',
        schema: pswdsSchema,
        // Define the permissions here
        permissions: {
            read: 'Admin',
            write: 'Admin',
            modify: 'Admin',
            delete: 'Admin',
        }
    }]
})

Since this collection is sensitive, only admins have access to it, if other users try to access a forbidden error will be thrown.

Note: For added security, you should create separate clients for backend operations and user operations. Usually in the request handler of any server framework, you get the ID and role of members and create a client for them.

Collection Hooks

Collection hooks are functions or callbacks that are triggered at specific points in the lifecycle of data operations (such as insert, update, delete) on a collection or table in a database. These hooks allow developers to execute custom logic in response to these operations, enabling tasks like data validation, transformation, logging, and enforcing business rules.

The available hooks that you can use are: | Hook Name | Description | | ------------------ | ------------------------------------------------------------------------------------- | | afterGetItem | A hook that is triggered after a getItem() operation. | | afterInsert | A hook that is triggered after an insert() operation. | | afterBulkInsert | A hook that is triggered after a bulkInsert() operation. | | afterRemove | A hook that is triggered after a remove() operation. | | afterUpdate | A hook that is triggered after an update() operation. | | beforeGetItem | A hook that is triggered before a getItem() operation. | | beforeInsert | A hook that is triggered before an insert() operation. | | beforeBulkInsert | A hook that is triggered before a bulkInsert() operation. | | beforeRemove | A hook that is called before a remove() operation. | | beforeBulkRemove | A hook that is called before a bulkRemove() operation. | | beforeUpdate | A hook that is triggered before an update() operation. | | beforeBulkUpdate | A hook that is triggered before a bulkUpdate() operation. | | onFailure | A hook that is triggered on any error or rejected Promise from any of the operations. |

To implement and data hook, add a hooks property to a collection definition, and add the event handler.

mongodb.defineDatabase({
    name: 'Auth',
    collections: [{ 
        name: 'Passwords',
        schema: pswdsSchema,
        permissions: {
            read: 'Admin',
            write: 'Admin',
            modify: 'Admin',
            delete: 'Admin',
        },
        // Add the hooks in the object below
        hooks: {
            beforeUpdate: (item, context) => {
                if (context.userRole !== 'Admin') {
                    throw new Error(`Unauthorized: User ${context.userId} is not allowed to perform update opoerations`);
                }
            }
        }
    }]
})

Creating Clients

Our MongoDB client offers lots of flexibilities for your needs, you can create different clients for different clusters of users, leading to increase of prodictivity.

Creating a Connection

Each client needs a defined connection to a cluster, and since you can create as many clients as you want, and some times you need multiple clients to be connected to the same cluster, you only need to define a collection once, and use it as many times as you want.

Let's start by defining a connection:

const localServer = mongodb.defineConnection('localServer', 'mongodb://localhost:27017');

console.log(localServer); // ⇨ 'localServer'

You can see that the defineConnection() method returns the connection name, so you can use it directly when creating clients, or you can use the name instead.

Creating a Client

To create a client, you need to pass an options object to the createClient method, one of which is the connection name. The connection property is required, while the rest of the options are optional.

In our example, we'll demonstrate how you can create clients in your application.

Create a System client. This type of client bypasses all the defined permissions, and is intended to keep track of things that are not user related.

/**A client that does NOT do user-related operations */
const systemClient = mongodb.createClient({
    name: 'localServer', // A name of a defined connection
    authorization: 'System'
});

You can also create a clinet for user operations. We'll use HyperCloud server framework to demonstrate how:

router.patch('/users/<:userId>', (request, response, next) => {
    const { userId } = request.params;
    if (!request.user.loggedIn || request.user.id !== userId) { return response.pages.unauthorized() }

    const dbClient = mongodb.createClient({
        name: 'localServer', // A name of a defined connection
        authorization: 'User',
        user: {
            id: request.user.id,
            role: request.user.role,
            loggedIn: request.user.loggedIn
        }
    });

    // Safely run oprations on any collection
    // ....
})

When defining a database client dynamically based on the user's data, the permissions and roles associated with that user are enforced directly within the client configuration. This ensures that unauthorized users cannot bypass the permissions set for their specific roles, thereby maintaining strict access control. By integrating user-specific data such as ID, role, and login status into the client creation process, you can securely perform database operations while ensuring that only authorized users can access or modify the data. This method provides a robust mechanism for safeguarding sensitive information and enforcing user-specific access policies.

Usage

It's easy to follow the auto-completion of the package.

Documentations will come soon ...

License

Please read the license from here.