Wednesday, November 19, 2014

MONGODB BASIC CONFIGURATION

1. Mongodb without authentication


Mongodb folder structure

 C:\\mongodb\\bin
 C:\\mongodb\\data
Start mongoDB without authentication

C:\mongodb\bin\mongod.exe --dbpath "C:\mongodb\data"

or

C:\mongodb\bin\mongod.exe --dbpath="C:\mongodb\data"


Default port is 27017

2. Enable authentication



First we need to start mongoDB without authentication

C:\mongodb\bin\mongod.exe --dbpath "C:\mongodb\data"

After that run following commands :

1. Run  mongo client with : mongo.exe
2. Use data base with : use admin

3. Add user and role : db.createUser({"user":"root","pwd":"123456","roles":[{"role":"readWriteAnyDatabase","db":"admin"},{"role":"userAdminAnyDatabase","db":"admin"},{"role":"dbAdminAnyDatabase","db":"admin"}]})

The object of root user(for easy to read)


db.createUser({
 "user":"root",
 "pwd":"123456",
 "roles":[
  {
   "role":"readWriteAnyDatabase",
   "db":"admin"
  },
  {
   "role":"userAdminAnyDatabase",
   "db":"admin"
  },
  {
   "role":"dbAdminAnyDatabase",
   "db":"admin"
  }
 ]
});


And start with authentication mode:

 #mongod.exe --dbpath="C:\mongodb\data" --auth



3. Creating window service with configuration file


mongo.cfg placed in c:\mongodb\etc\

systemLog:
   destination: file
   path: c:\\mongodb\\etc\\mongodb.log
   logAppend: true
storage:
   dbPath: c:\\mongodb\\data
   journal: 
      enabled: true
processManagement: 
   windowsService: 
      serviceName: t2i-mongodb-server
      displayName: T2i mongoDb server display name.
      description: The service for MongoDatabase
security: 
   authorization: enabled
net:
   bindIp: 127.0.0.1
   port: 27017


Command to start as service

"C:\mongodb\bin\mongod.exe" --config "C:\mongodb\etc\mongo.cfg" --install

Thursday, November 13, 2014

LINUX BASIC COMMON COMMANDS

Filter result:


grep

ex: filter all processes and ports of java

ps -e | grep java
netstat -tunap | grep java

Process and infomation :


Information about process
$ls -l /proc/$PID/exe
OR
$ps -p PID -o comm=
OR
$cat /proc/PID/cmdline

Kill process
sudo kill -9 PID

User and Group:


Login
#su - {user-name}

Login as root
#su -

check username
#whoami

logout
#logout

Extract & Compress file:


Extract
#tar -zxvf {file.tar.gz}
#tar -xf {file.tar.gz} -C /target/directory
#tar -xzf backup.tar.gz -C /target/directory
#unzip file.zip -d destination_folder

Download
#wget http://ftp.gnu.org/gnu/wget/wget-1.5.3.tar.gz  -P /target/directory

Restating the network service:


To restart the network service under RHEL / CentOS based systems, enter:
service network restart
OR
/etc/init.d/network restart

Check linux kernel version number :


Open a shell prompt (or a terminal) and type the following command to see your current Linux kernel version:

uname -r

Or type the following command
uname -mrs

To print all information, enter

uname -a

Type the following command to see Linux version info

cat /proc/version

Find Distribution Version :


Type the following command

cat /etc/*release

OR
lsb_release -a

Port & Firewall :


Port and process command
netstat -tunap

If you want to open a single port

open iptables file
vi /etc/sysconfig/iptables

Add below line to open port.

-A INPUT -m state --state NEW -m tcp -p tcp --dport 143 -j ACCEPT

For multiple, you can use the following instead (or repeat the above line multiple times):

-A INPUT -m state --state NEW -m tcp -p tcp -m multiport --dports 22,80,143 -j ACCEPT

service iptables save

Disable / Turn off Linux Firewall (Red hat/CentOS/Fedora Core)

Type the following two commands (you must login as the root user)

/etc/init.d/iptables save

/etc/init.d/iptables stop

Turn off firewall on boot

chkconfig iptables off

Enable / Turn on Linux Firewall (Red hat/CentOS/Fedora Core)

Type the following command to turn on iptables firewall

/etc/init.d/iptables start 

Turn on firewall on boot

chkconfig iptables on 

Linux / Unix - Checking Free Disk Space:


df command examples - to check free disk space

Type df -h or df -k to list free disk space

df -h

OR
df -k

Find Files and Folders in Linux :


find / -name "java" 

/: meaning is the root folder. hold systems
-name "java": all files have name is java.

Thursday, November 6, 2014

NODEJS - RUNNING A NODEJS SERVER AS A SERVICE ON LINUX


1. Download the project for testing:


The user logged in was: root

Download the demo server here

[root@homepc opt]# wget https://github.com/vanduc1102/nodejs-example/archive/daemon-bauth.tar.gz

[root@homepc opt]# tar -zxvf daemon-bauth.tar.gz

[root@homepc opt]# cd nodejs-example-daemon-bauth/

[root@homepc nodejs-example-daemon-bauth]# npm install

[root@hompec nodejs-example-daemon-bauth]# node index.js


You can open browser and test the application at localhost:3000

We had nodejs-example folder placed in /opt/nodejs-example-daemon-bauth

2. Create a service file in systemd:


Create file below in folder : /etc/systemd/system/
nodejs-example-service.service

[Unit]
Description=The nodejs-example server start

[Service]
WorkingDirectory=/opt/nodejs-example-daemon-bauth
ExecStart=/usr/bin/node index.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=nodejs-example-nodejs-server
User=root
Group=root

[Install]
WantedBy=multi-user.target

Load the service at first time:
#systemctl enable nodejs-example-service

Start service:
#systemctl start nodejs-example-service

View status of the service:
#systemctl status nodejs-example-service

Stop the service:
#systemctl stop nodejs-example-service

3. Testing the service:


[root@homepc system]# systemctl start  nodejs-example-service.service
[root@homepc system]# systemctl status nodejs-example-service.service
nodejs-example-service.service - The nodejs-example server start
Loaded: loaded (/etc/systemd/system/nodejs-example-service.service; enabled)
Active: active (running) since jeu 2014-11-06 19:18:02 ICT; 8s ago
Main PID: 3967 (node)
CGroup: name=systemd:/system/nodejs-example-service.service
└─3967 /usr/bin/node index.js
[root@homepc system]# ps -e | grep "node"
3967 ? 00:00:00 node
[root@homepc system]# kill 3967
[root@homepc system]# ps -e | grep "node"
4038 ? 00:00:00 node
[root@homepc system]# systemctl status nodejs-example-service.service
nodejs-example-service.service - The nodejs-example server start
Loaded: loaded (/etc/systemd/system/nodejs-example-service.service; enabled)
Active: active (running) since jeu 2014-11-06 19:18:02 ICT; 8s ago
Main PID: 4038 (node)
CGroup: name=systemd:/system/nodejs-example-service.service
└─4038 /usr/bin/node index.js
[root@homepc system]#

As you can see, After we kill the process, It will automatically create new one.

Thursday, October 30, 2014

nodejs - secured server with https connections

Previous post

Checkout

Checkout the code at github
If you can use command below for checkout and run the app.

vanduc@VGN-FZ290E:~/test2$ git clone --depth=10 https://github.com/vanduc1102/nodejs-example.git
vanduc@VGN-FZ290E:~/test2$ cd nodejs-example/
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 4-https
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js

HTTPS configuration 

For configuration HTTPS connection we need a key and self signed certification to make the SSL work.

Creating key/certificate pair very easy with only one line, if you already installed OpenSSL

openssl req -subj '/CN=localhost/O=mycompany/C=VN' -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout server.key -out server.crt

Code for HTTPS connection:


var options = {
  key: fs.readFileSync('./ssl/server.key'),
  cert: fs.readFileSync('./ssl/server.crt')
};
var server = https.createServer(options,app).listen(serverConfigure.sslPort, function () {
 var address,
        host = serverConfigure.host ? serverConfigure.host : 'localhost',
        port = serverConfigure.sslPort;
    address = host + ':' + port;
    console.log('HTTPS server is listenning on localhost:3443');
});


We will create HTTPS server by add option, the option is about the path of key and certificate,
the server will create with the option for SSL connection , express server by app variable.

HTTPS auto redirection

In order to protect our server (users still can access our server by HTTP connection). We need to redirect the user request to HTTPS connection.

There is some ways to make HTTP auto redirection
  1. inside nodejs code.
  2. configure firewall to auto forward.
We can simply configure inside nodejs code

function requireHTTPS(req, res, next) {
    if (!req.secure) {
        var addressSSL,
            host = serverConfigure.host ? serverConfigure.host : 'localhost',
            port = serverConfigure.sslPort;
        addressSSL = host + ':' + port;
        return res.redirect('https://' + addressSSL + req.url);
    }
    next();
}
if (serverConfigure.httpsAutoRedirection) {
    app.use(requireHTTPS);
}


If the option httpsAutoRedirection in serverConfigure file is true,  we will check every request to the server and redirect the request to HTTPS port.



Tuesday, October 21, 2014

NODEJS - Basic Access Authentication

Previous Post


This article is about how to do basic authentication with NodeJS.

Checkout my project on GitHub. For one who never checkout my project before.

vanduc@VGN-FZ290E:~/test2$ git clone --depth=10 https://github.com/vanduc1102/nodejs-example.git
vanduc@VGN-FZ290E:~/test2$ cd nodejs-example/
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 3-basic-auth
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js

For one who already checked out my project.

vanduc@VGN-FZ290E:~/test2/nodejs-example$ git pull
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 3-basic-auth
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js

You can login with username and password is  admin:123456

The code require authentication on server side:


var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var app = express();
app.use(bodyParser.json());
app.use(cookieParser());
app.use(session({
 secret: '1234567890QWERTY',
    saveUninitialized: true,
    resave: true}));
var realm = 'localhost';
function unauthorized(res, realm) {
    res.statusCode = 401;
    res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
    res.setHeader('Content-Type', 'text/html');
    res.end("This request requires HTTP authentication");
}
function checkLogin(username, password, callback){
 if(username =='admin' && password =='123456')
 {
  callback(null,username);
 }
 else
 {
  callback('worng user name',username);
 }
};
app.use(function (req, res, next) {
    var authorization = req.headers.authorization;
    var session = req.session;
    if (req.user) {
        console.log('User already stored in request : ' + req.user);
        return next();
    }

    if (!authorization) {
        return unauthorized(res, realm);
    }
    var parts = authorization.split(' ');
    if (parts.length !== 2) return next(error(400));
    var scheme = parts[0]
        , credentials = new Buffer(parts[1], 'base64').toString()
        , index = credentials.indexOf(':');
    if ('Basic' != scheme || index < 0)
    {
     return next(error(400));
    }
    var user = credentials.slice(0, index)
        , pass = credentials.slice(index + 1);
 if(session.user_id != ''&&session.user_id == user){
        return next();
    }
    //async check authentication
    checkLogin(user, pass, function (err, username) {
        if (err != null) {
            session.destroy();
            req.user = req.remoteUser = null;
            return unauthorized(res, realm);
        }
        req.user = req.remoteUser = user;
        session.user_id = user;
        next();
    })
});

Then we use the tricky code for doing the logout basic authentication:

$(document).ready(function(){
      $('span.logout').on('click',function(e){
           e.preventDefault();
                var xmlHttp;
                if (window.XMLHttpRequest) {
                    xmlHttp = new XMLHttpRequest();
                }
                // code for IE
                else if (window.ActiveXObject) {
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                }
                if (window.ActiveXObject) {
                    // IE clear HTTP Authentication
                    document.execCommand("ClearAuthenticationCache");
                    window.location.reload();
                } else {
                    xmlHttp.open("GET", window.location, true, "logout", "logout");
                    xmlHttp.send("");
                    xmlHttp.onreadystatechange = function () {
                        if (xmlHttp.readyState == 4) {
                            window.location.reload();
                        }
                    }
                }
                return false;
      });
    });

In order to secured your site with basic access authentication, You must provide SSL connection.
Otherwise it is not good solution.
Some disvantages of basic-auth is you cant modify the login pop-up, It depends on the browser provider.
The user credentials will store on browers cache .... :( very bad


Next Post



Saturday, October 18, 2014

Restore grub2 after install windows

The problem is after you install linux and then you install a windows 

For example after install Ubuntu 9.10 and then I install Windows operating system along with Ubuntu. The windows will override Master Boot Record on Hard driver , so from now when your computer boot up, you only can see Windows.

To solve the problem:

We need to have a CD version of Ubuntu 9.10. Boot our PC with live mode of Ubuntu 9.10
.Open Terminal ( Applications  > Accessories > Terminal)

(We suppose that the Ubuntu already installed on  partition sda3 of sda)

sudo -i (change user to  root user).

mount /dev/sda3 /mnt

grub-install --root-directory=/mnt/ /dev/sda

mount --bind /proc /mnt/proc

mount --bind /dev /mnt/dev

mount --bind /sys /mnt/sys

chroot /mnt update-grub

umount /mnt/sys

umount /mnt/dev

umount /mnt/proc

exit

Reboot your computer and enjoy !

Setting Global Environment Variables in LINUX

The easiest way to set an environment variable in CentOS is to use export as in :

vanduc@VGN-FZ290E:~/Downloads$export JAVA_HOME=/usr/lib/java/jdk1.7.0_71

vanduc@VGN-FZ290E:~/Downloads$export PATH=$PATH:$JAVA_HOME

However, variables set in such a manner are transient i.e. they will disappear the moment you exit the shell. Obviously this is not helpful when setting environment variables that need to persist even when the system reboots.

In such cases, you need to set the variables within the system wide profile

In CentOS (I’m using v5.2), the folder /etc/profile.d/ is the recommended place to add customizations to the system profile.

For example, when installing the Sun JDK, you might need to set the JAVA_HOME and JRE_HOME environment variables. In this case:
Create a new file called java.sh

vanduc@VGN-FZ290E:~/Downloads$ sudo vi /etc/profile.d/java.sh

Within this file, initialize the necessary environment variables

export JAVA_HOME=/usr/lib/java/jdk1.7.0_71

export JRE_HOME=$JAVA_HOME/jre

export PATH=$PATH:$JRE_HOME/bin

export PATH=$PATH:$JAVA_HOME/bin


Now when you restart your machine, the environment variables within java.sh will be automatically initialized (checkout /etc/profile if you are curious how the files in /etc/profile.d/ are loaded) .

If you want to load the environment variables within java.sh without having to restart the machine, you can use the source command as in:

vanduc@VGN-FZ290E:~/Downloads$ source /etc/profile.d/java.sh


Test command:

vanduc@VGN-FZ290E:~/Downloads$ java -version

java version "1.7.0_71"

Java(TM) SE Runtime Environment (build 1.7.0_71-b14)

Java HotSpot(TM) Server VM (build 24.71-b01, mixed mode)

vanduc@VGN-FZ290E:~/Downloads$

P/S : some common commands use to setup java environment

vanduc@VGN-FZ290E:~/Downloads$ cd Downloads/
vanduc@VGN-FZ290E:~/Downloads$ ls
google-chrome-stable_current_i386.deb jdk-7u71-linux-i586.tar.gz sublime-text_build-3065_i386.deb
vanduc@VGN-FZ290E:~/Downloads$ tar -zxvf jdk-7u71-linux-i586.tar.gz
vanduc@VGN-FZ290E:~/Downloads$ sudo mkdir /usr/lib/java
vanduc@VGN-FZ290E:~/Downloads$ mv jdk1.7.0_71/ /usr/lib/java/


Monday, October 13, 2014

NODEJS - CREATE STATIC SERVER WITH EXPRESS MIDDLEWARE

About NodJs

One of the great things about Node.js is that it has a built in HTTP server. This means you don't need Apache or nginx. This means serving a static site can be done in few lines of code. This article goes into how this can be achieved.

Express Static Middleware

Express has become the defacto Node.js web framework and it has great built in capabilities to serve static content. The nice thing is that not only can you serve static content you can also gzip compress it and cache it. But let's just start with the required package.json and a basic static server.

Let's start

1. Set up package.json file

Use command $npm init for creating package.json file

D:\static>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install  --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (static) static-server
version: (0.0.0) 0.0.1
description: this is an example how to create static server with nodejs
entry point: (index.js)
test command:
git repository:
keywords:
author: ducnguyen
license: (ISC)
About to write to D:\static\package.json:

{
  "name": "static-server",
  "version": "0.0.1",
  "description": "this is an example how to create static server with nodejs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "ducnguyen",
  "license": "ISC"
}


Is this ok? (yes) yes

D:\static>

After init we will have the contain of package.json file

{
  "name": "static-server",
  "version": "0.0.1",
  "description": "this is an example how to create static server with nodejs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "ducnguyen",
  "license": "ISC"
}

2. Install express module

Using command $npm install expess


Add contains for index.js file:


var express = require('express');
var app = express();
var http = require('http');
app.use(express.static(__dirname + '/public'));
var server = http.createServer(app).listen(3000, function () {
 console.log('server is listenning on localhost:3000');
});



The above code is very simple, it creates an Express server, adds the static middleware and finally starts listening on port 3000 .

The static middleware handles serving up the content from a directory. In this case the 'public' directory is served up and any content (HTML, CSS, JavaScript) will be available. This means if the public directory looks like:
index.html
js/boostrap.min.js
css/boostrap.min.css

Then you can request the root route '/' and you'll get index.html file and the index.html also load the css and js file of boostrap. This is all expected from a static server.
Now just start the server by type command in command line promt $node index.js, and go to bowser hit http://localhost:3000/

We can also specify the url of static server:


app.use('/static',express.static(__dirname + '/public'));


Now  instead of type http://localhost:3000/ we will have our static page at http://localhost:3000/static/

Command for checkout :


vanduc@VGN-FZ290E:~/test2$ git clone --depth=10 https://github.com/vanduc1102/nodejs-example.git
vanduc@VGN-FZ290E:~/test2$ cd nodejs-example/
vanduc@VGN-FZ290E:~/test2/nodejs-example$ git checkout -f 1-static
vanduc@VGN-FZ290E:~/test2/nodejs-example$ npm install
vanduc@VGN-FZ290E:~/test2/nodejs-example$ node index.js


1. You will clone my repository at depth=10 means you will get last 10 commits
2. Change your directory working directory nodejs-example
3. Change the checkout to the 1-static, this was the tags with for static version.
4. Installing nodejs module need to run my application.
5. Start the application and enjoy.

Next Post



Monday, June 9, 2014

Common SQL Commands

Delete all except:

DELETE FROM edu_subscription WHERE id NOT IN ( 
SELECT id FROM edu_subscription
WHERE status_value_code = 'YES'
UNION
SELECT id FROM edu_subscription
WHERE status_value_code = 'NO'
)

Wednesday, January 1, 2014

Horizontal list Sencha Tounch 2.1.1

Views:

Tile-View

Ext.define('MyApp.view.TileView', {
extend: 'Ext.dataview.DataView',
alias: 'widget.mydataview',

config: {
baseCls: 'tile-data-view',
height: '100%',
id: 'tile-view',
width: '100%',
itemCls: 'tile',
store: 'ThemeStore',
scrollable: {
directionLock: true,
direction: 'horizontal',
momentumEasing: {
momentum: {
acceleration: 30,
friction: 0.5
},
bounce: {
acceleration: 0.0001,
springTension: 0.9999,

},
minVelocity: 3
},
outOfBoundRestrictFactor: 0
},
inline: {
wrap: false
},
itemTpl: [
'

',
'


{name}

',
'


{numOfCourses} courses

',
'

'
]
},

initialize: function() {
this.callParent();
var me = this.container;
//me.setWidth(2080);
var el1 = Ext.get('MainContainer');
var parent = this.getParent();
//CSBfleXcroll.defer(1, window, [this.body.dom]);
//var scroller = me.getScrollable();
//console.info('My parent is : '+parent);
//console.info('Main container : '+el1.getHeight());
//console.info('scroller : '+ scroller);
}

});

My-Panel

Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.Panel',

requires: [
'MyApp.view.TileView'
],

config: {
layout: {
type: 'vbox'
},
scrollable: false,
items: [
{
xtype: 'titlebar',
docked: 'top',
itemId: 'top-bread-crumb',
items: [
{
xtype: 'button',
itemId: 'increase',
text: 'Increase'
},
{
xtype: 'button',
itemId: 'decrease',
text: 'Decrease'
}
]
},
{
xtype: 'mydataview',
itemId: 'tileview1',
flex: 1
}
],
listeners: [
{
fn: 'onIncreaseTap',
event: 'tap',
delegate: '#increase'
},
{
fn: 'onDecreaseTap',
event: 'tap',
delegate: '#decrease'
},
{
fn: 'onPanelPainted',
event: 'painted'
}
]
},

onIncreaseTap: function(button, e, eOpts) {
var tileView = this.down('#tile-view').container;
var h = tileView.getHeight();
var w = tileView.getWidth();
console.log('this get width : '+ this.getWidth());
console.log('height : '+ h + ' width : '+w);
tileView.setWidth(w+300);
},

onDecreaseTap: function(button, e, eOpts) {
var tileView = this.down('#tile-view').container;
var h = tileView.getHeight();
var w = tileView.getWidth();
console.log('this get width : '+ this.getWidth());
console.log('height : '+ h + ' width : '+w);
tileView.setWidth(w-300);
},

onPanelPainted: function(element, eOpts) {
console.log('on panel painted function');
this.containerHeight= this.element.getHeight();
this.containerWidth = this.element.getWidth();
console.log('h = '+ this.containerHeight +' w = '+ this.containerWidth);
var breadcrumb = this.down('#top-bread-crumb');
var h = breadcrumb.element.getHeight();
var w = breadcrumb.element.getWidth();
console.log('height = '+h +' widht = '+ w);
//this.setTileViewSize(h,w);
},

initialize: function() {
this.callParent();
var container = this.element;
this.containerHeight=0;
this.containerWidth=0;
console.log('container : '+container);
console.log('container width : '+ container.getWidth() + ' height : '+ container.getHeight());
var tileView = this.down('#tile-view').container;
tileView.setWidth(2080);
}

});

Store:

Ext.define('MyApp.store.ThemeStore', {
extend: 'Ext.data.Store',

requires: [
'MyApp.model.ThemeModel'
],

config: {
autoLoad: true,
model: 'MyApp.model.ThemeModel',
storeId: 'ThemeStore',
proxy: {
type: 'ajax',
url: 'data/test.json',
reader: {
type: 'json'
}
}
}
});

Model

Ext.define('MyApp.model.ThemeModel', {
extend: 'Ext.data.Model',

config: {
fields: [
{
name: 'code'
},
{
name: 'name'
},
{
name: 'numOfCourses'
}
]
}
});

Data

[
{
"code": "TH10",
"name": "Computer",
"numOfCourses": 5
},
{
"code": "TH11",
"name": "Midwifery",
"numOfCourses": 3
},
{
"code": "TH12",
"name": "Professional",
"numOfCourses": 7
},
{
"code": "TH13",
"name": "Sport and Exercise Science",
"numOfCourses": 4
},
{
"code": "TH14",
"name": "International Business",
"numOfCourses": 5
},
{
"code": "TH15",
"name": "Design Engineering",
"numOfCourses": 6
},
{
"code": "TH16",
"name": "Work Based Learning Studies",
"numOfCourses": 4
},
{
"code": "TH17",
"name": "Business Management",
"numOfCourses": 18
},
{
"code": "TH18",
"name": "Biology",
"numOfCourses": 4
},
{
"code": "TH2",
"name": "Languages",
"numOfCourses": 5
},
{
"code": "TH3",
"name": "Miscellaneous",
"numOfCourses": 36
},
{
"code": "TH5",
"name": "Financial",
"numOfCourses": 1
},
{
"code": "TH6",
"name": "Psychology",
"numOfCourses": 7
},
{
"code": "TH7",
"name": "Healthcare Science",
"numOfCourses": 5
},
{
"code": "TH8",
"name": "Criminology",
"numOfCourses": 6
},
{
"code": "TH9",
"name": "Other Course",
"numOfCourses": 6
}
]