Build a simple chat app with node.js and socket.io

To develop a real chat application, we have to put in place a real-time system of sending/receiving data. It will be impossible to do it with a relational database and Ajax calls. Thank’s to WebSocket and the library socket.io, it becomes easy.

You can follow this tutorial with my repo Github: https://github.com/ngrt/simpleChatApp

Technical stack

Here is the technical stack that you are using for this app :

WebSockets and socket.io

WebSockets is a protocol that allows a bilateral synchronous exchange between a client and a server.

In the classic web, a client requests to a server and a server responds sending it back the data. This system is impossible for a chat app.

In WebSockets, the server can send data to the client, but the client can too ! A WebSocket is a kind of communication pipe opened in two directions.

Socket.io is a library based on this protocol to make the use of WebSockets easier.

The Javascript mafia

Node.js is a Javascript back-end technology executed by the server as PHP, Ruby or Python. JavaScript uses events. Node.js keeps this particularity so it is easy to make asynchronous code.

Node.js comes with its own package manager: npm. It becomes easy to install, update, delete packages.

In this tutorial, we are going to use express.js. It’s a micro web framework based on node.js.

Set up of the development environnement

First of all, we need to configure our development environment.

The first thing to do is to start npm, our packages manager. To do so, open a new terminal, create a new repository which will contain our project, go in it and initialize npm:

$ mkdir createSimpleApp
$ cd createSimpleApp
$ npm init

npm will ask you for several information. If you want to skip that, press enter until the end. Now if you look at your project, we will find a new file : package.json. This file is listing all your dependencies.

So now, we are ready to install the packages needed to develop our chat app! We are going to need these packages:

  • express: the micro web application framework for node.js
  • Nodemon: a package that will detect any changes and restart our server. We will use it instead of the classic node command.
  • ejs: a template engine to simplify the production of HTML
  • socket.io: the famous package than manage WebSockets

To install them on our environment, it is super easy:

$ npm install --save package_name

I let you do the work for our 4 packages.

In your package.json, you could add this line into your scripts key:

“start”: “nodemon app”

With this line, you will be able to launch your app only with one commande using nodemon:

$ npm run start

Our environment is set up, we are ready to develop our application.

The chat app

Architecture of the app

First of all, we have to separate to part in the development of an application: the client part and the server part. We will have to develop the two parts to make our application up and running.

The server will be handled by node.js to make all the engineering (launch the packages and the website). This code will not be seen by the client.

The client part will be loaded on the computer of the client. He will have direct access to the files (html/css and js).

Server side:

We have to create the file app.js that will launch our server and all the packages.

This bunch of code is actually initializing our express app. If you go to http://localhost:3000, you will see a gentle message.

Now we just need to configure socket.io to be ready to deep dive into the WebSocket world.

Here, the io object will give us access to the socket.io library. io object is now listening to each connection to our app. Each time a new user is connecting, it will print out “New user connected” in our console.

If you try to reload our browser on localhost, nothing happened… Why ? Because our client side is not yet ready.

For the moment socket.io is only installed on the server part. Next, we will do the same work on the client side.

Client side

We just have to change a line in our app.js. In fact, we don’t want to display a « Hello world » message, but a really window with a chat box, inputs to write username/message and a send button. To do that we have to render an html file (which will be in our case an ejs file) when accessing the “/” root.

So you need to apply the render method to the res object.

In the other side, you will have to create a views folder, with an index.ejs file in it. The css will be in a public folder:

Our localhost:3000 will look like this :

So now that we have our basic template, we have to « install » socket.io on each client which will attempt to connect to our server. To do that, we have to import the socket.io library on the client side:

<script src=”https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>

The only way to work with socket.io is in a .js file. So at the end of your body add these lines:

<script src=”http://code.jquery.com/jquery-latest.min.js"></script>
<script src=”chat.js”></script>

And create a chat.js file in the public folder.

For the moment, just write this in it :

As you probably guessed, when the client will load this file, it will automatically connect and so create a new socket.

So when you refresh the page, we will see « New user connected » in your terminal.

Send and receive data

Username

When a user connects to our application, we will set him/her a default username, for example “anonymous”. To do that we have to go on the server side (app.js) and add a key to the socket. Actually, socket represent each client connected to our server.

We also will listen to any call made in « change_username ». If a message is sent to this event, the username will be changed.

On the client side, the goal is to do the opposite. Each time the button change username is clicked, the client will send an event with the new value.

Message

For the messages, it is the same principle!

chat.js:

app.js:

For the new_message event, you can see that we call the sockets property of io. It represents all the sockets connected. So this line will actually send a message to all the sockets. We want that to show a message sent by a user to all (and itself included).

Here is the final result of our chat app:

Little improvement

We can add a quick improvement to make our application more realistic. We will add the « XXX is typing… » message.

To do so, it is very easy.

After adding an HTML element in our index.ejs, we just add a jQuery event listener on typing and send a socket event named typing.

On the other side, we listen to typing and we broadcast a message. Broadcasting means sending a message to everyone else except for the socket that starts it.

Conclusion

See, this application is really easy to code. Before knowing the existence of WebSockets and socket.io, I thought this kind of application was really hard to code !

To improve this app, here is a list of functionalities to add:

  • A registration system with the possibility to chat in a one-to-one chatroom
  • History of all the conversations
  • Online/offline labels
  • Copy every features of WhatsApp !

Noufel Gouirhate

Introduction to Validation in React with Yup

The JavaScript Object Schema Validator and Object Parser to use with React

In this article we will visit why you should be using Yup in your React projects, what it does exactly, and how to make the most out of the package to simplify your code, with examples.

Yup is designed for front-end browser based use. If you are interested in server-side object schema validation with NodeJS, take a look at my article on Joi:

Why should you care about Yup?

Yup makes our lives far easier for validating the data our apps consume and manipulate, in an abstract way that does not interfere with the rest of our business logic.

Web apps built on JavaScript Frameworks are now highly interactive and mutable in and of themselves; that is what the end user has come to expect. With this comes a large amount of data exchange, whether it be from API requests, form submissions, or custom objects to handle our state.

We need to make sure we are delivering data that our components expect to work with, otherwise we will be dealing with unintended consequences in the form of failed component renders or app crashes — we don’t want this.

The general gist of Yup

So how does Yup work exactly?

With Yup, we create a Yup formatted object that resembles our intended schema for an object, and then use Yup utility functions to check if our data objects match this schema — hence validating them.

A Schema Object

Let’s use form validation as a use case for our Yup example.

Note: Form validation is by no means the only use case for Yup — use it to validate any object that you need to, whether you are retrieving data from your APIs or an external API library, or simply working with multiple objects or arrays within your project that need to adhere to a particular schema.

With that said, now imagine I am creating a checkout address form — which may resemble the following structure:

{ 
    email_address: email <required>
    full_name: string, <required>
    house_no: int,
    address_1: string <required>,
    address_2: string,
    post_code: string <required>
    timestamp: date <required>
}

This is the type of data I am expecting from this form, or my schema for a particular object. If my object does not match this schema, it is not valid.

Notice that I have treated the email_address field as an email data type. This is not an error. Yup can test whether a value is an email address with one method call . Likewise with our timestamp value — Yup can test whether this value is a date.

What does this look like as a Yup schema object? Something like this:

const checkoutAddressSchema = yup.object().shape({
  email_address: yup
      .string()
      .email()
      .required(),
  full_name: yup
      .string()
      .required(),
  house_no: yup
      .number()
      .required()
      .positive()
      .integer(),
  address_1: yup
      .string()
      .required(),
  address_2: yup
      .string(),
  post_code: yup
      .string()
      .required(),
  timestamp: yup
      .date()
      .default(() => (new Date()),
   }),
});

A Yup schema is an immutable object responsible for validating an object.

This code is self explanatory: We can see for ourselves the responsibility of this object in a detailed way without having to add a single comment.

Each validator has its own method. This granularity allows us as developers to combine as many validators as we see fit for our data validation.

Data types such as stringintegerbooleanarrayobject and date are all callable validators within Yup, making it simple for Yup newcomers to begin using the code.

However, Yup goes way beyond simple data types. In the above example we also use validators like emailrequired, and positive, allowing me to check whether a value is representative of an email address, whether a value exists and whether a number is positive respectively. (we also have notRequired to use for greater readability of your schema).

This is great, abstract, reusable design. We can even assign default values with an embedded function, as the above example demonstrates with the timestamp field:

 ...
   timestamp: yup
      .date()
      .default(() => (new Date()),
   }
...

default() can be anything you wish to assign: it takes any value. The function can be expanded and treated like any other to include any logic you need to process in order to generate a default value:

...
   timestamp: yup
      .date()
      .default(() => {
         //check for stuff           
         return new Date();
      }),
   }
...

Validating Objects with My Schema

Now we have a schema for our checkout address form, we can then use it to validate the data we receive from it. Let’s say I receive the following data:

let addressFormData = {
   email_address: 'ross@jkrbinvestments.com',
   full_name: 'Ross Bulat',
   house_no: null,
   address_1: 'My Street Name',
   post_code: 'AB01 0AB',
}

As you can see, the address_2 and timestamp fields are missing from here — but they are not required in our schema, so the object will still be valid.

From here I would like to demonstrate 3 things:

  • Check if my object is valid. So a true or false result of whether my object is indeed a valid checkout address object.
  • Validate the object. E.g. use my schema to fill in any default values. This also type casts our object.
  • Visit the cast() method of Yup, that type casts an object without validating it.

Checking if the object is valid

To do this, we use yup.isValid(), which will look like the following when applied to our example:

const valid = await checkoutAddressSchema.isValid(addressFormData);

isValid() returns a promise, so we can either treat this with async and await as demonstrated above, or use callback syntax:

checkoutAddressSchema
  .isValid(addressFormData)
  .then(function(valid) {
      
     //valid - true or false
  });

I prefer using await for cleaner syntax.

Validating the Object

In most cases we will require actually validating the object: process it to adhere to your schema expectations. In our example, we are expecting a timestamp value, and we have a default value if it is missing.

Let’s validate our address form with the following:

await checkoutAddressSchema.validate(addressFormData);

Now our object will be suitable for further processing.

Casting an Object

With the above example, validate(), we are checking whether our data is valid, and we are running validation on it. This is a handy shortcut that you may find you use the majority of time. However, we could just run an object through a cast() method that checks and fixes its types.

With our checkout address form, we may have a string that represents our house_no, whereas my schema expects an integer. cast() will fix this. It would also convert a timestamp string into our Date object if we indeed provided a timestamp string.

Cast is called like so:

checkoutAddressSchema.cast(addressFormData);

Indispensable Tool?

At this point it is becoming clear that Yup adds an extra vital layer of data security to our apps in a concise way. Validation becomes much less of a headache, and actually a joy to write and read because of the simplicity of the syntax and abstraction of the Yup library.

To expand your initial understanding of Yup, let’s visit some other useful methods available within the package.

Miscellaneous Useful Methods

  • Remember our form data structure outlined at the top of the article? This can be retrieved from a Yup object with the describe() methoddescribe() collects the object schema details and serializes them into a separate object.
  • Want to combine 2 schemas into one? Use the concat() method. Perhaps you are combining multiple objects into one API call body, and therefore want to validate the entire body with one Yup object. concat() will come in handy for this.
  • Aborting validation early. By default Yup runs through an entire validation process and collects errors as it runs, and returns them all once validation is complete. We may not want to do this. We can use abortEarly to stop validation execution as soon as the first error crops up. abortEarly is passed as an options argument within validate():
await checkoutAddressSchema.validate(addressFormData, { abortEarly: false })
  • Yup has some great string utilities, such as trim(), that removes whitespace around a string. uppercase() and lowercase() are available to enforce capitalising or not.
  • Yup also has some great number utilities, such as min() and max(), as well as round()morethan()lessthan(), and truncate().
  • Yup supports regex, allowing you to utilise regular expressions.

Installing Yup in React Projects

Let’s move on how to install Yup in your projects, and visit some resources available for further reading.

Visit the NPMJS page or Github project for their official documentation.

Install yup with npm using the following command:

npm i yup

Importing Yup

Yup has the flexibility to be imported as an entire library, or as separate components that only your component needs.

Import the entire library with:

import * as yup from 'yup';

I recommend importing the entire library as you start developing, saving you the hassle of revisiting your imports every time you introduce a new Yup object as your forms evolve. When your app is ready to be built, revisit Yup to check whether you are only using a limited amount of components — perhaps you are only utilising the required and string objects — in this case we can simply import those 2 things:

import { string, required } from 'yup';

Overall though, if you are utilizing more than around 5 components, it can become a code smell to be importing this many objects.

Where to go from here

Now you should have a solid understanding of what Yup is, why it is used, and perhaps some ideas on how it can be implemented in your projects!

Take some time to explore the documentation, which lists all the validators available. Only after exploring everything the package has to offer will you have a well-rounded understanding of how it can fully benefit your apps.

However, Yup can easily be built upon by simply refactoring your validators, so there is no harm in jumping straight into some implementation to increase familiarity of the workflow, before jumping into more documentation detail.

Yup may continue to play a greater role within your app as development progresses, therefore you may also find yourself refactoring some data structures to further take advantage of the Yup workflow in the form of abstracting your data into smaller, more reusable formats.

Ross Bulat

MS16-047: Security Update for SAM and LSAD Remote Protocols (3148527) (Badlock) (uncredentialed check)

Synopsis:

The remote Windows host is affected by an elevation of privilege vulnerability.

Description:

The remote Windows host is affected by an elevation of privilege vulnerability in the Security Account Manager (SAM) and Local Security Authority (Domain Policy) (LSAD) protocols due to improper authentication level negotiation over Remote Procedure Call (RPC) channels. A man-in-the-middle attacker able to intercept communications between a client and a server hosting a SAM database can exploit this to force the authentication level to downgrade, allowing the attacker to impersonate an authenticated user and access the SAM database.

Solution:

Microsoft has released a set of patches for Windows Vista, 2008, 7, 2008 R2, 2012, 8.1, RT 8.1, 2012 R2, and 10.

See More:

https://technet.microsoft.com/library/security/MS16-047

http://badlock.org/

Microsoft Windows Remote Desktop Protocol Server Man-in-the-Middle Weakness

Synopsis:

It may be possible to get access to the remote host.

Description:

The remote version of the Remote Desktop Protocol Server (Terminal Service) is vulnerable to a man-in-the-middle (MiTM) attack. The RDP client makes no effort to validate the identity of the server when setting up encryption. An attacker with the ability to intercept traffic from the RDP server can establish encryption with the client and server without being detected. A MiTM attack of this nature would allow the attacker to obtain any sensitive information transmitted, including authentication credentials.

This flaw exists because the RDP server stores a hard-coded RSA private key in the mstlsapi.dll library. Any local user with access to this file (on any Windows system) can retrieve the key and use it for this attack.

Solution:

– Force the use of SSL as a transport layer for this service if supported, or/and

– Select the ‘Allow connections only from computers running Remote Desktop with Network Level Authentication’ setting if it is available.

More help:
http://www.oxid.it/downloads/rdp-gbu.pdf

http://www.nessus.org/u?8033da0d

http://technet.microsoft.com/en-us/library/cc782610.aspx

JavaScript fundamentals for better developers

JavaScript has primitives, objects and functions. All of them are values. All are treated as objects, even primitives.

Primitives

Number, boolean, string, undefined and null are primitives.

Number

There is only one number type in JavaScript, the double precision floating point. Decimal numbers’ arithmetic is inexact.

As you may already know, 0.1 + 0.2 does not make 0.3 . But with integers, the arithmetic is exact, so 1+2 === 3 .

Numbers inherit methods from the Number.prototype object. Methods can be called on numbers:

(123).toString();  //"123"
(1.23).toFixed(1); //"1.2"

There are global functions for converting to numbers : parseInt()parseFloat()and Number():

parseInt("1")       //1
parseInt("text")    //NaN
parseFloat("1.234") //1.234
Number("1")         //1
Number("1.234")     //1.234

Invalid arithmetic operations or invalid conversions will not throw an exception, but will result in the NaN “Not-a-Number” value. isNaN() can detect NaN .

The + operator can add or concatenate.

1 + 1      //2
"1" + "1"  //"11"
1 + "1"    //"11"

String

A string stores a series of Unicode characters. The text can be inside double quotes "" or single quotes ''.

Strings inherit methods from String.prototype. They have methods like : substring()indexOf() and concat() .

"text".substring(1,3) //"ex"
"text".indexOf('x')   //2
"text".concat(" end") //"text end"

Strings, like all primitives, are immutable. For example concat() doesn’t modify the existing string but creates a new one.

Boolean

A boolean has two values : true and false .
The language has truthy and falsy values.
falsenullundefined''(empty string), and NaN are falsy. All other values, including all objects, are truthy.

The truthy value is evaluated to true when executed in a boolean context. Falsy value is evaluated to false. Take a look at the next example displaying the false branch.

let text = '';
if(text) {
  console.log("This is true");
} else {
  console.log("This is false");
}

Objects

An object is a dynamic collection of key-value pairs. A key is a string. The value can be a primitive, object, or function.

The simplest way to create an object is to use an object literal:

let obj = {
  message : "A message",
  doSomething : function() {}
}

We can read, add, edit and remove an object’s properties at any time.

  • get: object.nameobject[expression]
  • set: object.name = value, object[expression] = value
  • delete: delete object.namedelete object[expression]
let obj = {}; //create empty object
obj.message = "A message"; //add property
obj.message = "A new message"; //edit property
delete obj.message; //delete property

Objects can be used as hash-maps. A simple hash-map can be created using Object.create(null) :

let french = Object.create(null);
french["yes"] = "oui";
french["no"]  = "non";
french["yes"];//"oui"

If you want to make the object immutable, use Object.freeze() .

All object’s properties are public. Object.keys() can be used to iterate over all properties.

function logProperty(name){
  console.log(name); //property name
  console.log(obj[name]); //property value
}
Object.keys(obj).forEach(logProperty);

Primitives vs. Objects

Primitives are treated like objects, in the sense that they have methods but they are not objects.

Primitives are immutable, and objects are mutable.

Variables

Variables can be defined using varlet and const.

var declares and optionally initializes a variable. The value of a variable that is not initialize is undefined . Variables declared with var have a function scope.

The let declaration has a block scope.

A variable declared with const cannot be reassigned. Its value, however, can still be mutable. const freezes the variable, Object.freeze() freezes the object. The const declaration has a block scope.

The scope of a variable declared outside any function is global.

Array

JavaScript has array-like objects. An array is implemented using an object. Elements are accessed using their indices. Indices are converted to strings and used as names for retrieving values. In the next example arr[1] gives the same value as arr['1'] : arr[1] === arr['1'] .

A simple array like let arr = ['A', 'B', 'C'] is emulated using an object like the one below:

{
  '0': 'A',
  '1': 'B',
  '2': 'C'
}

Removing values from the array with delete will leave holes. splice() can be used to avoid the problem, but it can be slow.

let arr = ['A', 'B', 'C'];
delete arr[1];
console.log(arr); // ['A', empty, 'C']
console.log(arr.length); // 3

JavaScript’s arrays don’t throw index out of range exceptions. If the index is not available, it will return undefined.

Stack and queue can easily be implemented using the array methods:

let stack = [];
stack.push(1);           // [1]
stack.push(2);           // [1, 2]
let last = stack.pop();  // [1]
console.log(last);       // 2
let queue = [];
queue.push(1);           // [1]
queue.push(2);           // [1, 2]
let first = queue.shift();//[2]
console.log(first);      // 1

Functions

Functions are independent units of behavior.

Functions are objects. Functions can be assigned to variables, stored in objects or arrays, passed as an argument to other functions, and returned from functions.

There are three ways to define a function:

  • Function Declaration (aka Function Statement)
  • Function Expression (aka Function Literal)
  • Arrow Function

The Function Declaration

  • function is the first keyword on the line
  • it must have a name
  • it can be used before definition. Function declarations are moved, or “hoisted”, to the top of their scope.
function doSomething(){}

The Function Expression

  • function is not the first keyword on the line
  • the name is optional. There can be an anonymous function expression or a named function expression.
  • it needs to be defined, then it can execute
  • it can auto-execute after definition (called “IIFE” Immediately Invoked Function Expression)
let doSomething = function() {}

Arrow Function

The arrow function is a sugar syntax for creating an anonymous function expression.

let doSomething = () => {};

Arrow functions don’t have their own this and arguments.

Function invocation

A function, defined with the function keyword, can be invoked in different ways:

  • Function form
doSomething(arguments)
  • Method form
theObject.doSomething(arguments)
theObject["doSomething"](arguments)
  • Constructor form
new doSomething(arguments)
  • Apply form
 doSomething.apply(theObject, [arguments])
 doSomething.call(theObject, arguments)
  • Bind form
let doSomethingWithObject = doSomething.bind(theObject);
doSomethingWithObject();

Functions can be invoked with more or fewer arguments than declared in the definition. The extra arguments will be ignored, and the missing parameters will be set to undefined.

Functions have two pseudo-parameters: this and arguments.

this

this represents the function’s context. Only functions defined with the function keyword have their own this context. Its value depends on how the function was invoked. See below the values of this depending on the doSomething() function invocation form:

function doSomething(){
  console.log(this)
}
+------------+------------------+
| Form       | this             |
+------------+-------------------
| Function   | window/undefined |
| Method     | theObject        |
| Constructor| the new object   |
| apply      | theObject        |  
| bind       | theObject        |    
+------------+------------------+

arguments

The arguments pseudo-parameter gives all the arguments used at invocation. It’s an array-like object, but not an array. It lacks the array methods.

function reduceToSum(total, value){
  return total + value;
}
  
function sum(){
  let args = Array.prototype.slice.call(arguments);
  return args.reduce(reduceToSum, 0);
}
sum(1,2,3);

An alternative is the new rest parameters syntax. This time args is an array object.

function sum(...args){
  return args.reduce(reduceToSum, 0);
}

return

A function with no return statement returns undefined. Pay attention to the automatic semi-colon insertion when using return. The following function will not return an empty object, but rather an undefined one.

function getObject(){ 
  return 
  {
  }
}
getObject()

To avoid the issue, use { on the same line as return :

function getObject(){ 
  return {
  }
}

Dynamic Typing

JavaScript has dynamic typing. Values have types, variables do not. Types can change at run time.

function log(value){
  console.log(value);
}
log(1);
log("text");
log({message : "text"});

The typeof() operator can check the type of a variable.

let n = 1;
typeof(n);   //number
let s = "text";
typeof(s);   //string
let fn = function() {};
typeof(fn);  //function

A Single Thread

The main JavaScript runtime is single threaded. Two functions can’t run at the same time. The runtime contains an Event Queue which stores a list of messages to be processed. There are no race conditions, no deadlocks. However, the code in the Event Queue needs to run fast. Otherwise the browser will become unresponsive and will ask to kill the task.

Exceptions

JavaScript has an exception handling mechanism. It works like you may expect, by wrapping the code using the try/catch statement. The statement has a single catch block that handles all exceptions.

It’s good to know that JavaScript sometimes has a preference for silent errors. The next code will not throw an exception when I try to modify a frozen object:

let obj = Object.freeze({});
obj.message = "text";

Strict mode eliminates some JavaScript silent errors. "use strict"; enables strict mode.

Prototype Patterns

Object.create(), Constructor Function, and class build objects over the prototype system.

Consider the next example:

let service = {
 doSomething : function() {}
}
let specializedService = Object.create(service);
console.log(specializedService.__proto__ === service); //true

I used Object.create() to build a new object specializedService which has the service object as its prototype. This means that doSomething() is available on the specializedService object. It also means that the __proto__property of specializedService points to the service object.

Let’s now build a similar object using class.

class Service {
 doSomething(){}
}
class SpecializedService extends Service {
}
let specializedService = new SpecializedService();
console.log(specializedService.__proto__ === SpecializedService.prototype);

All methods defined in the Service class will be added to the Service.prototype object. Instances of the Service class will have the same prototype (Service.prototype) object. All instances will delegate method calls to the Service.prototype object. Methods are defined once on Service.prototype and then inherited by all instances.

Prototype chain

Objects inherit from other objects. Each object has a prototype and inherits their properties from it. The prototype is available through the “hidden” property __proto__ .

When you request a property which the object does not contain, JavaScript will look down the prototype chain until it either finds the requested property, or until it reaches the end of the chain.

Functional Patterns

JavaScript has first class functions and closures. These are concepts that open the way for Functional Programming in JavaScript. As a result, higher order functions are possible.

Closure is an inner function that has access to the parent function’s variables, even after the parent function has executed.

A higher order function is a function that takes another function as an input, returns a function, or does both.

For more on the JavaScript functional side take a look at:

Discover the power of first class functions

How point-free composition will make you a better functional programmer

Here are a few function decorators you can write from scratch

Why you should give the Closure function another chance

Make your code easier to read with Functional Programming