default/cve5/cve.js (286 lines of code) (raw):
//
// CVE.js
// Filename: cve.js
//
// Author: Ben Nott <pajexali@gmail.com>
//
// Description: Exposes MITRE CVE API through CveServices using Service Worker
// middleware for credential storage and request handling.
//
// Copyright 2022, Ben Nott <pajexali@gmail.com>.
// See LICENSE for a full copy of the license.
//
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([], factory);
    } else if (typeof module === 'object' && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory();
    } else {
        // Browser globals (root is window)
        root.returnExports = factory();
    }
}(typeof self !== 'undefined' ? self : this, function () {
    class NoCredentialsError extends Error {};
    class CredentialError extends Error {};
    class MiddlewareError extends Error {};
    class CveServices {
        constructor(serviceUri = 'https://cveawg.mitre.org/api', swPath = 'sw.js') {
            //console.log('called constructer');
            this._middleware = new CveServicesMiddleware(serviceUri, swPath);
            //this._request = null;
            //this._channels = [];
        }
        // Session mgmt
        login(user, org, key) {
            //console.log('called login');
            return this._middleware.setCredentials({ user, org, key });
        }
        logout() {
            //console.log("Called logout");
            return this._middleware.destroy();
        }
        active() {
            return this._middleware ? true : false;
        }
        // Inter-instance communication.
        on(chanName) {
            return new Promise(resolve => {
                let bc = new BroadcastChannel(chanName);
                bc.onmessage = msg => {
                    resolve(msg.data);
                };
            });
        }
        // API methods
        getCveIds(args) {
            return this._middleware.get('cve-id', args);
        };
        reserveCveIds(args) {
            return this._middleware.post('cve-id', args);
        }
        reserveCveId(year = new Date().getFullYear()) {
            return this._middleware.orgName
                       .then(orgName => {
                           let args = {
                               amount: 1,
                               cve_year: year,
                               short_name: orgName,
                           };
                           return this.reserveCveIds(args);
                       });
        }
        reserveSeqCveIds(n = 1, year = new Date().getFullYear()) {
            return this._middleware.orgName
                .then(orgName => {
                    let args = {
                        amount: n,
                        cve_year: year,
                        short_name: orgName,
                        batch_type: 'sequential',
                    };
                    return this.reserveCveIds(args);
                });
        }
        reserveNonSeqCveIds(n = 1, year = new Date().getFullYear()) {
            return this._middleware.orgName
                .then(orgName => {
                    let args = {
                        amount: n,
                        cve_year: year,
                        short_name: orgName,
                        batch_type: 'nonsequential',
                    };
                    return this.reserveCveIds(args);
                });
        }
        getCveId(id) {
            return this._middleware.get('cve-id/'.concat(id));
        }
        updateCveId(id, state, org = undefined) {
            let record = { state };
            if (org)
                record['org'] = org;
            return this._middleware.put('cve-id/'.concat(id), record);
        }
        getCves(opts) {
            let query;
            if (opts) {
                query = {};
                if (opts.hasOwnProperty('state'))
                    query['cveState'] = opts.state;
                if(opts.hasOwnProperty('modBefore'))
                    query['cveRecordFilteredTimeModifiedLt'] = opts.modBefore;
                if(opts.hasOwnProperty('modAfter'))
                    query['cveRecordFilteredTimeModifiedGt'] = opts.modAfter;
                if(opts.hasOwnProperty('count'))
                    query['countOnly'] = 1;
                if (opts.hasOwnProperty('assignerShort'))
                    query['assignerShortName'] = opts.assignerShort;
                if (opts.hasOwnProperty('assigner'))
                    query['assigner'] = opts.assigner;
            }
            return this._middleware.get('cve', query);
        }
        getCve(id) {
            return this._middleware.get('cve/'.concat(id));
        }
        createCve(id, schema) {
            return this._middleware.post('cve/'.concat(id, '/cna'), undefined, schema);
        }
        updateCve(id, schema) {
            return this._middleware.put('cve/'.concat(id, '/cna'), undefined, schema);
        }
        createRejectedCve(id, schema) {
            return this._middleware.post('cve/'.concat(id, '/reject'), undefined, schema);
        }
        updateRejectedCve(id, schema) {
            return this._middleware.put('cve/'.concat(id, '/reject'), undefined, schema);
        }
        getOrg() {
            return this._middleware.orgName.then(orgName => orgName);
        }
        getOrgInfo() {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.get('org/'.concat(orgName)));
        }
        updateOrgInfo(orgInfo) {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.get('org/'.concat(orgName), orgInfo));
        }
        createOrgUser(userInfo) {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.post(`org/${orgName}/user`, undefined, userInfo));
        }
        updateOrgUser(username, userInfo) {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.put(`org/${orgName}/user/${username}`, userInfo, undefined));
        }
        resetOrgUserApiKey(username) {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.put(`org/${orgName}/user/${username}/reset_secret`));
        }
        getOrgUsers() {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.get(`org/${orgName}/users`));
        }
        getOrgIdQuota() {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.get(`org/${orgName}/id_quota`));
        }
        getOrgUser(username) {
            return this._middleware.orgName
                .then(orgName =>
                    this._middleware.get(`org/${orgName}/user/${username}`));
        }
    };
    class CveServicesMiddleware {
        constructor(serviceUri = 'https://cveawg.mitre.org/api', swPath = 'sw.js') {
            this.serviceUri = serviceUri;
            this.registration;
            this.swPath = swPath;
            if (!('serviceWorker' in navigator)) {
                throw MiddlewareError("Service Workers are not available in your browser.");
            }
        }
        get worker() {
            if (this.registration) {
                return Promise.resolve(this.registration.active);
            }
            let serviceUri = this.serviceUri;
            let initWorker = (worker) => {
                let init_msg = { type: 'init',
                                serviceUri };
                this.simpleMessage(worker, init_msg);
            };
            return navigator.serviceWorker.register(this.swPath)
                .then(reg => {
                    this.registration = reg;
                    if (reg.installing != undefined) {
                        return new Promise(resolve => {
                            let worker = reg.installing;
                            worker.addEventListener('statechange', (e) => {
                                if (e.target.state == 'activated') {
                                    initWorker(e.target);
                                    resolve(e.target);
                                }
                            });
                        });
                    } else {
                        initWorker(reg.active);
                        return reg.active;
                    }
                });
        }
        simpleMessage(worker, msg) {
            return new Promise(resolve => {
                let channel = new MessageChannel();
                channel.port1.onmessage = (msg) => {
    		    if('debug' in msg)
                        console.log(msg);
                    resolve(msg.data);
                };
                worker.postMessage(msg, [channel.port2]);
            }, reject => {
                worker.onmessageerror = reject;
            });
        }
        send(msg) {
            return this.worker.then(worker => {
                return this.simpleMessage(worker, msg).then(res => {
                    if(typeof res === 'object' && 'error' in res) {
                        return Promise.reject(res);
                    } else {
                        return res;
                    }
                });
            });
        }
        serviceRequest(request) {
            let msg = {
                type: 'request',
                ...request,
            };
            return this.send(msg);
        }
        echo() {
            return this.send({type: 'echo'});
        }
        setCredentials(creds) {
            let msg = {
                type: 'login',
                creds,
            };
            return this.send(msg);
        }
        get(path, query) {
            let req = {
                method: 'GET',
                path, query
            };
            return this.serviceRequest(req);
        }
        post(path, query, body) {
            let req = {
                method: 'POST',
                path, query, body
            };
            return this.serviceRequest(req);
        }
        put(path, query, body) {
            let req = {
                method: 'PUT',
                path, query, body
            };
            return this.serviceRequest(req);
        }
        get orgName() {
            let msg = {
                type: 'getOrg',
            };
            var o = this.send(msg);
            return o;
        }
        destroy() {
            // Broadcast logout event
            let bc = new BroadcastChannel('logout');
            bc.postMessage({'error': 'LOGOUT', message: 'The user has logged out'});
            if (this.registration) {
                //this.send({type: 'destroy'});
                this.registration.unregister();
                this.registration = undefined;
                return Promise.resolve(true);
            } else {
                return Promise.resolve(false);
            }
        }
    }
    if (window != undefined) {
        window.CveServices = CveServices;
        window.CveServicesMiddleware = CveServicesMiddleware;
    }
    return CveServices;
}));