<commit_before>'use strict';

import { IResponse, ISimpleResponse } from '../types/tokens/standard-tokens';
import * as express from 'express';
import { error as logError } from './logger';
import { Error401, Error403, Error404, StatusError } from './errors';

/**
 * A decorator for transforming an async express function handler.
 * Transforms the promise's response into a serialized json with
 * a 200 response code.
 * @param errCode The type of error code to raise for errors
 */
export function j200( code: number = 200, errCode: number = 500 ) {
  return function( target: any, propertyKey: string, descriptor: PropertyDescriptor ) {
    const originalMethod = descriptor.value;

    // Editing the descriptor/value parameter
    descriptor.value = function() {
      const res = arguments[ 1 ] as express.Response;
      const result: Promise<any> | any | null = originalMethod.apply( this, arguments );
      if ( result && result instanceof Promise ) {
        result.then( result => {
          res.setHeader( 'Content-Type', 'application/json' );
          res.status( code ).json( result );
        } ).catch( ( err: Error ) => {

          res.setHeader( 'Content-Type', 'application/json' );
          if ( err instanceof StatusError )
            res.status( err.status );
          else
            res.status( errCode )
          res.statusMessage = encodeURIComponent( err.message );
          res.json( { message: err.message } );
        } );
      }
    };

    // return edited descriptor as opposed to overwriting the descriptor
    return descriptor;
  }
}

/**
 * Helper function to return a status 200 json object of type T
 */
export function okJson<T extends IResponse>( data: T, res: express.Response ) {
  res.setHeader( 'Content-Type', 'application/json' );
  res.end( JSON.stringify( data ) );
}

/**
 * Helper function to return a status 500 json object of type T
 */
export function errJson( err: Error, res: express.Response ) {
  logError( err.message );

  if ( err instanceof Error401 )
    res.status( 401 );
  else if ( err instanceof Error403 )
    res.status( 403 );
  else if ( err instanceof Error404 )
    res.status( 404 );
  else
    res.status( 500 );<commit_msg>Added function decorator for admin permissions<commit_after>import Factory from '../core/controller-factory';
import { IResponse, ISimpleResponse } from '../types/tokens/standard-tokens';
import * as express from 'express';
import { error as logError } from './logger';
import { Error401, Error403, Error404, StatusError } from './errors';
import { IAuthReq } from '../types/tokens/i-auth-request';
import { UserPrivileges } from '../core/user-privileges';

/**
 * A decorator for transforming an async express function handler.
 * Transforms the promise's response into a serialized json with
 * a 200 response code.
 * @param errCode The type of error code to raise for errors
 */
export function j200( code: number = 200, errCode: number = 500 ) {
  return function( target: any, propertyKey: string, descriptor: PropertyDescriptor ) {
    const originalMethod = descriptor.value;

    // Editing the descriptor/value parameter
    descriptor.value = function() {
      const res = arguments[ 1 ] as express.Response;
      const result: Promise<any> | any | null = originalMethod.apply( this, arguments );
      if ( result && result instanceof Promise ) {
        result.then( result => {
          res.setHeader( 'Content-Type', 'application/json' );
          res.status( code ).json( result );
        } ).catch( ( err: Error ) => {

          res.setHeader( 'Content-Type', 'application/json' );
          if ( err instanceof StatusError )
            res.status( err.status );
          else
            res.status( errCode )
          res.statusMessage = encodeURIComponent( err.message );
          res.json( { message: err.message } );
        } );
      }
    };

    // return edited descriptor as opposed to overwriting the descriptor
    return descriptor;
  }
}

/**
 * Checks if the request is a logged in user. If not then a 400 error is thrown
 * for either permission (403) or lack of authorization (401)
 */
export function admin() {
  return function( target: any, propertyKey: string, descriptor: PropertyDescriptor ) {
    const originalMethod = descriptor.value;

    descriptor.value = async function() {
      const req = arguments[ 0 ] as IAuthReq;
      const res = arguments[ 1 ] as express.Response;
      const session = await Factory.get( 'sessions' ).getSession( req );

      if ( !session )
        throw new Error401( 'You must be logged in to make this request' );

      if ( session )
        await Factory.get( 'sessions' ).setSessionHeader( session, req, res );

      req._user = session.user;
      req._isAdmin = session.user.privileges <= UserPrivileges.Admin;

      if ( session.user.privileges! > UserPrivileges.Admin )
        throw new Error403( `You don't have permission to make this request` );

      const result = originalMethod.apply( this, arguments );
      return result;
    };

    // return edited descriptor as opposed to overwriting the descriptor
    return descriptor;
  }
}

/**
 * Helper function to return a status 200 json object of type T
 */
export function okJson<T extends IResponse>( data: T, res: express.Response ) {
  res.setHeader( 'Content-Type', 'application/json' );
  res.end( JSON.stringify( data ) );
}

/**
 * Helper function to return a status 500 json object of type T
 */
export function errJson( err: Error, res: express.Response ) {
  logError( err.message );

  if ( err instanceof Error401 )
    res.status( 401 );
  else if ( err instanceof Error403 )
    res.status( 403 );
  else if ( err instanceof Error404 )
    res.status( 404 );
  else
    res.status( 500 );
{'fraction_non_alphanumeric': 0.1109764542936288, 'fraction_numerical': 0.019909972299168976, 'mean_word_length': 2.9139566395663956, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3289193', 'n_tokens_mistral': 1655, 'n_tokens_neox': 1539, 'n_words': 567}