diff --git a/.meteor/packages b/.meteor/packages
index 113c4d33f64661fa4ebf308f55045ad3d78527dd..ac1dbedc0d013b0e22e969b8b06669dcd6fb0865 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -85,3 +85,4 @@ todda00:friendly-slugs
 underscorestring:underscore.string
 yasaricli:slugify
 yasinuslu:blaze-meta
+rocketchat:authorization
diff --git a/.meteor/versions b/.meteor/versions
index b09ffefd8ab57310f6488ac362c2295d0a8de9c6..be5c92d06392264932fde52ebb51d1f219ddc2d2 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -6,6 +6,7 @@ accounts-meteor-developer@1.0.4
 accounts-oauth@1.1.5
 accounts-password@1.1.1
 accounts-twitter@1.0.4
+alanning:roles@1.2.13
 aldeed:simple-schema@1.3.3
 arunoda:streams@0.1.17
 autoupdate@1.2.1
@@ -100,6 +101,7 @@ reactive-dict@1.1.0
 reactive-var@1.0.5
 reload@1.1.3
 retry@1.0.3
+rocketchat:authorization@0.0.1
 rocketchat:autolinker@0.0.1
 rocketchat:colors@0.0.1
 rocketchat:custom-oauth@1.0.0
diff --git a/client/lib/chatMessages.coffee b/client/lib/chatMessages.coffee
index 2ecd8cc4634c19cc36020176c53370ffa6256977..15f9289252f6931044889f92a48ad86661295e92 100644
--- a/client/lib/chatMessages.coffee
+++ b/client/lib/chatMessages.coffee
@@ -40,11 +40,15 @@ class @ChatMessages
 		return -1
 
 	edit: (element, index) ->
-		return unless RocketChat.settings.get 'Message_AllowEditing'
+		id = element.getAttribute("id")
+		message = ChatMessage.findOne { _id: id } 
+		hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid)
+		editAllowed = RocketChat.settings.get 'Message_AllowEditing'
+		editOwn = message?.u?._id is Meteor.userId()
+
+		return unless hasPermission or (editAllowed and editOwn)
 		return if element.classList.contains("system")
 		this.clearEditing()
-		id = element.getAttribute("id")
-		message = ChatMessage.findOne { _id: id, 'u._id': Meteor.userId() }
 		this.input.value = message.msg
 		this.editing.element = element
 		this.editing.index = index or this.getEditingIndex(element)
diff --git a/client/methods/deleteMessage.coffee b/client/methods/deleteMessage.coffee
index f6a02bf90b2d2cd2084fa2cbe58f2840ef28ac5e..24e418d6d28b09c253f3f83967f8e3b90dc451d8 100644
--- a/client/methods/deleteMessage.coffee
+++ b/client/methods/deleteMessage.coffee
@@ -3,9 +3,14 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error 203, t('general.User_logged_out')
 
-		if not RocketChat.settings.get 'Message_AllowDeleting'
+		hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid)
+		deleteAllowed = RocketChat.settings.get 'Message_AllowDeleting'
+		deleteOwn = message?.u?._id is Meteor.userId()
+
+		unless hasPermission or (deleteAllowed and deleteOwn)
 			throw new Meteor.Error 'message-deleting-not-allowed', t('Message_deleting_not_allowed')
 
+
 		Tracker.nonreactive ->
 			ChatMessage.remove
 				_id: message._id
diff --git a/client/methods/updateMessage.coffee b/client/methods/updateMessage.coffee
index 1366c4e31cd2ea0d41ea5eec7cdebaa80100a3e2..773bff4a1676498545abb7b402d8acacfa64c2a0 100644
--- a/client/methods/updateMessage.coffee
+++ b/client/methods/updateMessage.coffee
@@ -3,7 +3,13 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error 203, t('User_logged_out')
 
-		if not RocketChat.settings.get 'Message_AllowEditing'
+		originalMessage = ChatMessage.findOne message._id
+
+		hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid)
+		editAllowed = RocketChat.settings.get 'Message_AllowEditing'
+		editOwn = originalMessage?.u?._id is Meteor.userId()
+
+		unless hasPermission or (editAllowed and editOwn)
 			throw new Meteor.Error 'message-editing-not-allowed', t('Message_editing_not_allowed')
 
 		Tracker.nonreactive ->
diff --git a/client/stylesheets/base.less b/client/stylesheets/base.less
index cb84db26fd1efc49567e9c0d86075dd2f13248e3..a12b94f2d8806bbeecc60ca1f253e2bd2821e3c1 100644
--- a/client/stylesheets/base.less
+++ b/client/stylesheets/base.less
@@ -2374,14 +2374,14 @@ a.github-fork {
 		display: none;
 		cursor: pointer;
 	}
-	&.own:hover:not(.system) .edit-message {
+	&:hover:not(.system) .edit-message {
 		display: inline-block;
 	}
 	.delete-message {
 		display: none;
 		cursor: pointer;
 	}
-	&.own:hover:not(.system) .delete-message {
+	&:hover:not(.system) .delete-message {
 		display: inline-block;
 	}
 	.user {
diff --git a/client/views/admin/admin.coffee b/client/views/admin/admin.coffee
index 07d4c7eaa98aa2a633c38540f97607cc5888ec24..9ab84108dea21037e2cc6b90db6853ff8a38e9c6 100644
--- a/client/views/admin/admin.coffee
+++ b/client/views/admin/admin.coffee
@@ -1,6 +1,4 @@
 Template.admin.helpers
-	isAdmin: ->
-		return Meteor.user().admin is true
 	group: ->
 		group = FlowRouter.getParam('group')
 		group ?= Settings.findOne({ type: 'group' })?._id
diff --git a/client/views/admin/admin.html b/client/views/admin/admin.html
index 9bb7f03c4bebf5abaa9992ead276e3506cec8fef..b559af0e10cb1f03f1386205baa5b43a2a3939a6 100644
--- a/client/views/admin/admin.html
+++ b/client/views/admin/admin.html
@@ -7,7 +7,7 @@
 			</h2>
 		</head>
 		<div class="content">
-			{{#unless isAdmin}}
+			{{#unless hasPermission 'view-privileged-setting'}}
 				<p>You are not authorized to view this page.</p>
 			{{else}}
 				{{#with group}}
diff --git a/client/views/admin/adminFlex.html b/client/views/admin/adminFlex.html
index 164c694c210ff0664fbbc82b62fef8a7dc8eabaa..cc7ebf8731708dcf75d1fb6fe316469810cd3f40 100644
--- a/client/views/admin/adminFlex.html
+++ b/client/views/admin/adminFlex.html
@@ -7,24 +7,35 @@
 	<div class="content">
 		<div class="wrapper">
 			<ul>
-				<li>
-					<a href="{{pathFor 'admin-statistics'}}" class="admin-link">{{_ "Statistics"}}</a>
-				</li>
-				<li>
-					<a href="{{pathFor 'admin-rooms'}}" class="admin-link">{{_ "Rooms"}}</a>
-				</li>
-				<li>
-					<a href="{{pathFor 'admin-users'}}" class="admin-link">{{_ "Users"}}</a>
-				</li>
-				
+				{{#if hasPermission 'view-statistics'}}
+					<li>
+						<a href="{{pathFor 'admin-statistics'}}" class="admin-link">{{_ "Statistics"}}</a>
+					</li>
+				{{/if}}
+
+				{{#if hasPermission 'view-room-administration'}}
+					<li>
+						<a href="{{pathFor 'admin-rooms'}}" class="admin-link">{{_ "Rooms"}}</a>
+					</li>
+				{{/if}}
+
+				{{#if hasPermission 'view-user-administration'}}
+					<li>
+						<a href="{{pathFor 'admin-users'}}" class="admin-link">{{_ "Users"}}</a>
+					</li>
+				{{/if}}
+
 				<h3 class="add-room">
 					{{_ "Settings"}}
 				</h3>
-				{{#each groups}}
-				<li>
-					<a href="{{pathFor 'admin' group=_id}}" class="admin-link">{{_ i18nLabel}}</a>
-				</li>
-				{{/each}}
+
+				{{#if hasPermission 'view-privileged-setting'}}
+					{{#each groups}}
+					<li>
+						<a href="{{pathFor 'admin' group=_id}}" class="admin-link">{{_ i18nLabel}}</a>
+					</li>
+					{{/each}}
+				{{/if}}
 			</ul>
 		</div>
 	</div>
diff --git a/client/views/admin/adminStatistics.coffee b/client/views/admin/adminStatistics.coffee
index 4622e627e507a723fafc6ed5b3726bf8a0159f4a..8c27a0374efde26b96442c78e7e1845b886cdf52 100644
--- a/client/views/admin/adminStatistics.coffee
+++ b/client/views/admin/adminStatistics.coffee
@@ -1,6 +1,4 @@
 Template.adminStatistics.helpers
-	isAdmin: ->
-		return Meteor.user().admin is true
 	isReady: ->
 		return Template.instance().ready.get()
 	statistics: ->
diff --git a/client/views/admin/adminStatistics.html b/client/views/admin/adminStatistics.html
index fd02286c166ed1b5e888091668c79d3df8b076b7..f039362a8ea9340bf240c4ca74a783acc837e5cc 100644
--- a/client/views/admin/adminStatistics.html
+++ b/client/views/admin/adminStatistics.html
@@ -7,7 +7,7 @@
 			</h2>
 		</head>
 		<div class="content">
-			{{#unless isAdmin}}
+			{{#unless hasPermission 'view-statistics'}}
 				<p>You are not authorized to view this page.</p>
 			{{else}}
 				{{#if isReady}}
diff --git a/client/views/admin/rooms/adminRoomInfo.coffee b/client/views/admin/rooms/adminRoomInfo.coffee
index ccc7ce451b9856da00cbe0a29051b88a122c607b..731ea8daf1cb41907a8edaf3f89a3f088cadcbbc 100644
--- a/client/views/admin/rooms/adminRoomInfo.coffee
+++ b/client/views/admin/rooms/adminRoomInfo.coffee
@@ -1,4 +1,7 @@
 Template.adminRoomInfo.helpers
+	canDeleteRoom: ->
+		return RocketChat.authz.hasAtLeastOnePermission("delete-#{@t}")
+
 	type: ->
 		return if @t is 'd' then 'at' else if @t is 'p' then 'lock' else 'hash'
 	name: ->
diff --git a/client/views/admin/rooms/adminRoomInfo.html b/client/views/admin/rooms/adminRoomInfo.html
index fc35afc68209f21684550a9304f1e20ff49a0f66..090f36d5e8984416513aa1488e3a5e1b08230da1 100644
--- a/client/views/admin/rooms/adminRoomInfo.html
+++ b/client/views/admin/rooms/adminRoomInfo.html
@@ -1,14 +1,20 @@
 <template name="adminRoomInfo">
-	<div>
-		<h3><a href="{{route}}"><i class="icon-{{type}}"></i> {{name}}</a></h3>
-	</div>
-	<div>
-		<h3>{{_ "Users"}}:</h3>
-		{{#each usernames}}
-			{{.}}<br />
-		{{/each}}
-	</div>
-	<nav>
-		<button class='button delete red'><span><i class='icon-trash'></i> {{_ "Delete"}}</span></button>
-	</nav>
+	{{#unless hasPermission 'view-room-administration'}}
+		<p>You are not authorized to view this page.</p>
+	{{else}}
+		<div>
+			<h3><a href="{{route}}"><i class="icon-{{type}}"></i> {{name}}</a></h3>
+		</div>
+		<div>
+			<h3>{{_ "Users"}}:</h3>
+			{{#each usernames}}
+				{{.}}<br />
+			{{/each}}
+		</div>
+		{{#if canDeleteRoom}}
+		<nav>
+			<button class='button delete red'><span><i class='icon-trash'></i> {{_ "Delete"}}</span></button>
+		</nav>
+		{{/if}}
+	{{/unless}}
 </template>
\ No newline at end of file
diff --git a/client/views/admin/rooms/adminRooms.coffee b/client/views/admin/rooms/adminRooms.coffee
index 82b9995d6da8bc23784c7721f784690f2f9bd322..b871209f47571f11fb3af860f009ebd5836a2a5a 100644
--- a/client/views/admin/rooms/adminRooms.coffee
+++ b/client/views/admin/rooms/adminRooms.coffee
@@ -1,6 +1,4 @@
 Template.adminRooms.helpers
-	isAdmin: ->
-		return Meteor.user().admin is true
 	isReady: ->
 		return Template.instance().ready?.get()
 	rooms: ->
diff --git a/client/views/admin/rooms/adminRooms.html b/client/views/admin/rooms/adminRooms.html
index e9e358203619e65b6207173d5d2ca0297bb45ad2..ce0454d58f062a1f79639afd1a31a6cb2f59e3f9 100644
--- a/client/views/admin/rooms/adminRooms.html
+++ b/client/views/admin/rooms/adminRooms.html
@@ -7,7 +7,7 @@
 			</h2>
 		</head>
 		<div class="content">
-			{{#unless isAdmin}}
+			{{#unless hasPermission 'view-room-administration'}}
 				<p>You are not authorized to view this page.</p>
 			{{else}}
 				<form class="search-form" role="form">
diff --git a/client/views/admin/users/adminUserChannels.html b/client/views/admin/users/adminUserChannels.html
index a2f020d077f569b0de5516bf28066da0a4fd1a38..af72dcbbad0e95647200bd38ea81c5f7472fd765 100644
--- a/client/views/admin/users/adminUserChannels.html
+++ b/client/views/admin/users/adminUserChannels.html
@@ -1,5 +1,9 @@
 <template name="adminUserChannels">
-	<div class="user-info-channel">
-		<h3><a href="{{route}}"><i class="icon-{{type}}"></i> {{name}}</a></h3>
-	</div>
+	{{#unless hasPermission 'view-full-other-user-info'}}
+		<p>You are not authorized to view this page.</p>
+	{{else}}
+		<div class="user-info-channel">
+			<h3><a href="{{route}}"><i class="icon-{{type}}"></i> {{name}}</a></h3>
+		</div>
+	{{/unless}}
 </template>
\ No newline at end of file
diff --git a/client/views/admin/users/adminUserEdit.html b/client/views/admin/users/adminUserEdit.html
index d00a9875e0c0f814f542ae7b676a1fe480ab53d1..686f999ffdba88b0c4db402a401fba8d0247fbf8 100644
--- a/client/views/admin/users/adminUserEdit.html
+++ b/client/views/admin/users/adminUserEdit.html
@@ -1,19 +1,23 @@
 <template name="adminUserEdit">
-	<div class="about clearfix">
-		<form class="edit-form">
-			<h3>{{name}}</h3>
-			<div class="input-line">
-				<label for="name">{{_ "Name"}}</label>
-				<input type="text" id="name" autocomplete="off" value="{{name}}">
-			</div>
-			<div class="input-line">
-				<label for="username">{{_ "Username"}}</label>
-				<input type="text" id="username" autocomplete="off" value="{{username}}">
-			</div>
-		</form>
-	</div>
-	<nav>
-		<button class='button button-block cancel secondary'><span>{{_ "Cancel"}}</span></button>
-		<button class='button button-block blue save'><span>{{_ "Save"}}</span></button>
-	</nav>
+	{{#unless hasPermission 'edit-other-user-info'}}
+		<p>You are not authorized to view this page.</p>
+	{{else}}
+		<div class="about clearfix">
+			<form class="edit-form">
+				<h3>{{name}}</h3>
+				<div class="input-line">
+					<label for="name">{{_ "Name"}}</label>
+					<input type="text" id="name" autocomplete="off" value="{{name}}">
+				</div>
+				<div class="input-line">
+					<label for="username">{{_ "Username"}}</label>
+					<input type="text" id="username" autocomplete="off" value="{{username}}">
+				</div>
+			</form>
+		</div>
+		<nav>
+			<button class='button button-block cancel secondary'><span>{{_ "Cancel"}}</span></button>
+			<button class='button button-block blue save'><span>{{_ "Save"}}</span></button>
+		</nav>
+	{{/unless}}
 </template>
\ No newline at end of file
diff --git a/client/views/admin/users/adminUserInfo.coffee b/client/views/admin/users/adminUserInfo.coffee
index 17fef2107ec6d80e51b8c2b433610b34ec854579..90c5bdda538390e7622a80e3655e7b58cddb386b 100644
--- a/client/views/admin/users/adminUserInfo.coffee
+++ b/client/views/admin/users/adminUserInfo.coffee
@@ -1,6 +1,4 @@
 Template.adminUserInfo.helpers
-	isAdmin: ->
-		return Meteor.user()?.admin is true
 	name: ->
 		return if @name then @name else TAPi18next.t 'project:Unnamed'
 	email: ->
@@ -20,6 +18,9 @@ Template.adminUserInfo.helpers
 				@utcOffset = "+#{@utcOffset}"
 
 			return "UTC #{@utcOffset}"
+	hasAdminRole: ->
+		console.log 'hasAdmin: ', RocketChat.authz.hasRole(@_id, 'admin')
+		return RocketChat.authz.hasRole(@_id, 'admin')
 
 Template.adminUserInfo.events
 	'click .deactivate': (e) ->
diff --git a/client/views/admin/users/adminUserInfo.html b/client/views/admin/users/adminUserInfo.html
index 645f560e9d4dcdd7edf580ffd3aac8ab461d1779..bbf17a35256a33f93940752f647eda05d47f5d04 100644
--- a/client/views/admin/users/adminUserInfo.html
+++ b/client/views/admin/users/adminUserInfo.html
@@ -1,19 +1,25 @@
 <template name="adminUserInfo">
-	{{#if isAdmin}}
-		{{> userInfo user=.}}
-		<nav>
-			<button class='button lightblue edit-user button-block'><span><i class='icon-edit'></i> {{_ "Edit"}}</span></button>
-			{{#if admin}}
+	{{> userInfo user=.}}
+	<nav>
+		{{#if hasPermission 'edit-other-user-info'}}
+		<button class='button lightblue edit-user button-block'><span><i class='icon-edit'></i> {{_ "Edit"}}</span></button>
+		{{/if}}
+		{{#if hasPermission 'assign-admin-role'}}
+			{{#if hasAdminRole}}
 			<button class='button lightblue remove-admin button-block'><span><i class='icon-shield'></i> {{_ "Remove_Admin"}}</span></button>
 			{{else}}
 			<button class='button lightblue make-admin button-block'><span><i class='icon-shield'></i> {{_ "Make_Admin"}}</span></button>
 			{{/if}}
+		{{/if}}
+		{{#if hasPermission 'edit-other-user-active-status'}}
 			{{#if active}}
 			<button class='button deactivate button-block'><span><i class='icon-block'></i> {{_ "Deactivate"}}</span></button>
 			{{else}}
 			<button class='button activate button-block'><span><i class='icon-ok-circled'></i> {{_ "Activate"}}</span></button>
 			{{/if}}
-			<button class='button delete red button-block'><span><i class='icon-trash'></i> {{_ "Delete"}}</span></button>
-		</nav>
-	{{/if}}
+		{{/if}}
+		{{#if hasPermission 'delete-user'}}
+		<button class='button delete red button-block'><span><i class='icon-trash'></i> {{_ "Delete"}}</span></button>
+		{{/if}}
+	</nav>
 </template>
\ No newline at end of file
diff --git a/client/views/admin/users/adminUsers.coffee b/client/views/admin/users/adminUsers.coffee
index e1fc43f0f32c12f751688ec6ba219ea4d153803d..89834d56db5b3e4f60f3fd0ed7549ec181d395e6 100644
--- a/client/views/admin/users/adminUsers.coffee
+++ b/client/views/admin/users/adminUsers.coffee
@@ -1,6 +1,4 @@
 Template.adminUsers.helpers
-	isAdmin: ->
-		return Meteor.user().admin is true
 	isReady: ->
 		return Template.instance().ready?.get()
 	users: ->
diff --git a/client/views/admin/users/adminUsers.html b/client/views/admin/users/adminUsers.html
index 28921562e118f7fa711c8e8ad2b352c517de3728..e85242b85f58436b2020ee16b18d7eeba9834a89 100644
--- a/client/views/admin/users/adminUsers.html
+++ b/client/views/admin/users/adminUsers.html
@@ -7,7 +7,7 @@
 			</h2>
 		</head>
 		<div class="content">
-			{{#unless isAdmin}}
+			{{#unless hasPermission 'view-user-administration'}}
 				<p>You are not authorized to view this page.</p>
 			{{else}}
 				<form class="search-form" role="form">
diff --git a/client/views/app/message.coffee b/client/views/app/message.coffee
index 1b58609d16afb999f471fbf3903d36c9bae67bef..bdd7fb52b13b6082532825bb72f00407e38420c3 100644
--- a/client/views/app/message.coffee
+++ b/client/views/app/message.coffee
@@ -40,9 +40,16 @@ Template.message.helpers
 	pinned: ->
 		return this.pinned
 	canEdit: ->
-		return RocketChat.settings.get 'Message_AllowEditing'
+		if RocketChat.authz.hasAtLeastOnePermission('edit-message', this.rid )
+			return true
+
+		return RocketChat.settings.get('Message_AllowEditing') and this.u?._id is Meteor.userId()
+
 	canDelete: ->
-		return RocketChat.settings.get 'Message_AllowDeleting'
+		if RocketChat.authz.hasAtLeastOnePermission('delete-message', this.rid )
+			return true
+
+		return RocketChat.settings.get('Message_AllowDeleting') and this.u?._id is Meteor.userId()
 	canPin: ->
 		return RocketChat.settings.get 'Message_AllowPinning'
 	showEditedStatus: ->
diff --git a/client/views/app/room.coffee b/client/views/app/room.coffee
index 29712c677b1a3a82a42cebba795b54e9624379a6..d71bf3f5407e1c13c4d25c2f6c910470b2621a37 100644
--- a/client/views/app/room.coffee
+++ b/client/views/app/room.coffee
@@ -104,7 +104,10 @@ Template.room.helpers
 	canEditName: ->
 		roomData = Session.get('roomData' + this._id)
 		return '' unless roomData
-		return roomData.u?._id is Meteor.userId() and roomData.t in ['c', 'p']
+		if roomData.t in ['c', 'p']
+			return RocketChat.authz.hasAtLeastOnePermission('edit-room', this._id)
+		else
+			return ''
 
 	canDirectMessage: ->
 		return Meteor.user()?.username isnt this.username
@@ -183,9 +186,6 @@ Template.room.helpers
 	maxMessageLength: ->
 		return RocketChat.settings.get('Message_MaxAllowedSize')
 
-	isAdmin: ->
-		return Meteor.user()?.admin is true
-
 	utc: ->
 		if @utcOffset?
 			return "UTC #{@utcOffset}"
diff --git a/client/views/app/sideNav/channels.coffee b/client/views/app/sideNav/channels.coffee
index 7dffc0db7b284f974057bc422a437b88929b5be9..5d715a1453bcfb9a07d81a13888b778b5370eff5 100644
--- a/client/views/app/sideNav/channels.coffee
+++ b/client/views/app/sideNav/channels.coffee
@@ -10,8 +10,11 @@ Template.channels.helpers
 
 Template.channels.events
 	'click .add-room': (e, instance) ->
-		SideNav.setFlex "createChannelFlex"
-		SideNav.openFlex()
+		if RocketChat.authz.hasAtLeastOnePermission('create-c')
+			SideNav.setFlex "createChannelFlex"
+			SideNav.openFlex()
+		else 
+			e.preventDefault()	
 
 	'click .more-channels': ->
 		SideNav.setFlex "listChannelsFlex"
diff --git a/client/views/app/sideNav/channels.html b/client/views/app/sideNav/channels.html
index e4b3cec776b270c56f32de03e87cc1bbfdcfe5a4..82defaa8d0df2658848f2d3038014af9b5346a58 100644
--- a/client/views/app/sideNav/channels.html
+++ b/client/views/app/sideNav/channels.html
@@ -1,7 +1,9 @@
 <template name="channels">
 	<h3 class="add-room {{isActive}}">
 		{{_ "Channels"}}
-		<i class="a-plus"></i>
+		{{#if hasPermission 'create-c'}}
+			<i class="a-plus"></i>
+		{{/if}}
 	</h3>
 	<ul>
 		{{#each rooms}}
diff --git a/client/views/app/sideNav/listChannelsFlex.coffee b/client/views/app/sideNav/listChannelsFlex.coffee
index 1f3332b6b071804fdb858273c341d49d8b384849..1e9aa4f4c6bdfa07869497ae3ff53ae3aeec10ed 100644
--- a/client/views/app/sideNav/listChannelsFlex.coffee
+++ b/client/views/app/sideNav/listChannelsFlex.coffee
@@ -10,7 +10,8 @@ Template.listChannelsFlex.events
 		SideNav.closeFlex()
 
 	'click footer .create': ->
-		SideNav.setFlex "createChannelFlex"
+		if RocketChat.authz.hasAtLeastOnePermission( 'create-c')
+			SideNav.setFlex "createChannelFlex"
 
 	'mouseenter header': ->
 		SideNav.overArrow()
diff --git a/client/views/app/sideNav/listChannelsFlex.html b/client/views/app/sideNav/listChannelsFlex.html
index 573c33e1722cb9c2406c33ca084829cf53e44ec8..86ee731e9b077d8ae9221726d4f963063e3b6e7f 100644
--- a/client/views/app/sideNav/listChannelsFlex.html
+++ b/client/views/app/sideNav/listChannelsFlex.html
@@ -21,7 +21,9 @@
 	</div>
 	<footer>
 		<div>
+		{{#if hasPermission 'create-c'}}
 			<button class="button clean create">{{_ "Create_new"}}</button>
+		{{/if}}
 		</div>
 	</footer>
 </template>
diff --git a/client/views/app/sideNav/privateGroups.coffee b/client/views/app/sideNav/privateGroups.coffee
index 7e729c5af148c0731036a37afd06b08573fe398b..1b577816fe42cf312e14c9d049e0b315e52e3210 100644
--- a/client/views/app/sideNav/privateGroups.coffee
+++ b/client/views/app/sideNav/privateGroups.coffee
@@ -16,8 +16,11 @@ Template.privateGroups.helpers
 
 Template.privateGroups.events
 	'click .add-room': (e, instance) ->
-		SideNav.setFlex "privateGroupsFlex"
-		SideNav.openFlex()
+		if RocketChat.authz.hasAtLeastOnePermission('create-p')
+			SideNav.setFlex "privateGroupsFlex"
+			SideNav.openFlex()
+		else
+			e.preventDefault()
 
 	'click .more-groups': ->
 		SideNav.setFlex "listPrivateGroupsFlex"
diff --git a/client/views/app/sideNav/privateGroups.html b/client/views/app/sideNav/privateGroups.html
index 22db34a7c6f383a63fb8070bbac4928569c15b29..2d5685cc45576cdb9d78a3928e9237c419362caa 100644
--- a/client/views/app/sideNav/privateGroups.html
+++ b/client/views/app/sideNav/privateGroups.html
@@ -1,7 +1,9 @@
 <template name="privateGroups">
 	<h3 class="add-room {{isActive}}">
 		{{_ "Private_Groups"}}
-		<i class="a-plus"></i>
+		{{#if hasPermission 'create-p'}}
+			<i class="a-plus"></i>
+		{{/if}}
 	</h3>
 	<ul>
 		{{#each rooms}}
diff --git a/client/views/app/sideNav/sideNav.coffee b/client/views/app/sideNav/sideNav.coffee
index 78633f2189e02250aa07545cb59eb923aedc8521..6038e3608c7248da6261c9bb04255cf5e67c464d 100644
--- a/client/views/app/sideNav/sideNav.coffee
+++ b/client/views/app/sideNav/sideNav.coffee
@@ -1,6 +1,5 @@
 Template.sideNav.helpers
-	isAdmin: ->
-		return Meteor.user()?.admin is true
+
 	flexTemplate: ->
 		return SideNav.getFlex().template
 	flexData: ->
diff --git a/client/views/app/sideNav/userStatus.coffee b/client/views/app/sideNav/userStatus.coffee
index cf77f86ce4765a6ac8a3f85e929cb8ad4fb0138c..b722e4d2e2740af39b3d2d463d64c75f2938b9dc 100644
--- a/client/views/app/sideNav/userStatus.coffee
+++ b/client/views/app/sideNav/userStatus.coffee
@@ -17,8 +17,8 @@ Template.userStatus.helpers
 			username: username
 		}
 
-	isAdmin: ->
-		return Meteor.user()?.admin is true
+	showAdminOption: ->
+		return RocketChat.authz.hasAtLeastOnePermission( ['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting'])
 
 Template.userStatus.events
 	'click .options .status': (event) ->
diff --git a/client/views/app/sideNav/userStatus.html b/client/views/app/sideNav/userStatus.html
index 97e782c1e4458fd9e1f3c5ad4fb5ffc81992d8f5..a2c749354c3878ee80210c65fc92c6f84ca57859 100644
--- a/client/views/app/sideNav/userStatus.html
+++ b/client/views/app/sideNav/userStatus.html
@@ -18,7 +18,7 @@
 					<a href="" data-status="busy" class="status busy"><span>{{_ "Busy" context="male"}}</span></a>
 					<a href="" data-status="offline" class="status offline"><span>{{_ "Invisible"}}</span></a>
 					<a href="" id="account" class='account-link'><i class="icon-sliders"></i><span>{{_ "My_Account"}}</span></a>
-					{{#if isAdmin}}
+					{{#if showAdminOption }}
 						<a href="" id="admin" class='account-link'><i class="icon-wrench"></i><span>{{_ "Administration"}}</span></a>
 					{{/if}}
 					<a href="" id="logout"><i class="icon-logout"></i><span>{{_ "Logout"}}</span></a>
diff --git a/client/views/app/userInfo.coffee b/client/views/app/userInfo.coffee
index 2e6a19b7ca132e7c3c2989fa835cb98303532097..f94d4bb837d1f707d33b62c498ef31676c4ee182 100644
--- a/client/views/app/userInfo.coffee
+++ b/client/views/app/userInfo.coffee
@@ -1,6 +1,4 @@
 Template.userInfo.helpers
-	isAdmin: ->
-		return Meteor.user()?.admin is true
 	utc: ->
 		if @utcOffset?
 			if @utcOffset > 0
diff --git a/client/views/app/userInfo.html b/client/views/app/userInfo.html
index c8a5d18a7c8822b3fa43041131b9ea86df092616..6eadfa93a376d4cf40894289df57572c74a90c72 100644
--- a/client/views/app/userInfo.html
+++ b/client/views/app/userInfo.html
@@ -37,7 +37,7 @@
 				<h3 title="{{username}}"><i class="status-{{status}}"></i> {{username}}</h3>
 				<p>{{name}}</p>
 				{{#if utc}}<p><i class="icon-clock"></i>{{userTime}} (UTC {{utc}})</p>{{/if}}
-				{{#if isAdmin}}
+				{{#if hasPermission 'view-full-other-user-info'}}
 					{{#each emails}} <p><i class="icon-mail"></i> {{address}}{{#if verified}}&nbsp;<i class="icon-ok"></i>{{/if}}</p> {{/each}}
 					{{#each phone}} <p><i class="icon-phone"></i> {{phoneNumber}}</p> {{/each}}
 					{{#if lastLogin}} <p><i class="icon-calendar"></i> {{_ "Created_at"}}: {{createdAt}}</p> {{/if}}
diff --git a/packages/rocketchat-authorization/README.md b/packages/rocketchat-authorization/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..239b085c856dc0d1280af7d604b5f5a40c2d2eb7
--- /dev/null
+++ b/packages/rocketchat-authorization/README.md
@@ -0,0 +1,41 @@
+Supports role or permission based authorization, and defines the association between them. 
+
+A user is associated with role(s), and a role is associated with permission(s).  This package depends on alanning:roles for the role/user association, while the role/permission association is handled internally.  Thus, the underlying alanning:roles has no concept of a permission or the association between a role and permission.   
+
+Authorization checks can be done based on a role or permission.  However, permission based checks are preferred because they loosely associate an action with a role.  For example:
+
+```
+# permission based check
+if hasPermission(userId, 'edit-message') ...
+	# action is loosely associated to role via permission.  Thus action can be revoked
+	# at runtime by removing the permission for user's role instead of modifying the action code.
+
+# role based check
+if hasRole(userId, ['admin','site-moderator','moderator'])
+	# action is statically associated with the role
+	# action code has to be modified to add/remove role authorization
+
+```
+
+Usage:
+```
+# assign user to moderator role.  Permissions scoped globally
+# user can moderate (e.g. edit channel name, delete private group message) for all rooms
+RocketChat.authz.addUsersToRoles(userId, 'moderator')
+
+# assign user to moderator role.  Permissions scoped to the specified room
+# user can moderate (e.g. edit channel name, delete private group message) for only one room specified by the roomId
+RocketChat.authz.addUsersToRoles(userId, 'moderator', roomId )
+
+# check if user can modify message for any room
+RocketChat.authz.hasPermission(userId, 'edit-message')
+
+# check if user can modify message for the specified room.  Also returns true if user
+# has 'edit-message' at global scope.
+RocketChat.authz.hasPermission(userId, 'edit-message', roomId)
+```
+
+Notes:
+1. Roles are statically defined.  UI needs to be implemented to dynamically assign permission(s) to a Role
+2. 'admin', 'moderator', 'user' role identifiers should NOT be changed (unless you update the associated code) because they are referenced when creating users and creating rooms.  
+3. edit, delete message permissions are at either the global or room scope.  i.e. role with edit-message with GLOBAL scope can edit ANY message regardless of the room type.  However, role with edit-message with room scope can only edit messages for the room.  The global scope is associated with the admin role while the "room-scoped" permission is assigned to the room "moderator" (room creator).  If we want a middle ground that allows for edit-message for only channel/group/direct, then we need to create individual edit-c-message, edit-p-message, edit-d-message permissions. 
diff --git a/packages/rocketchat-authorization/client/hasPermission.coffee b/packages/rocketchat-authorization/client/hasPermission.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5155bf54c486b533ad4daa88aaee23662077d545
--- /dev/null
+++ b/packages/rocketchat-authorization/client/hasPermission.coffee
@@ -0,0 +1,40 @@
+atLeastOne = (toFind, toSearch) ->
+	console.log 'toFind: ', toFind if window.rocketDebug
+	console.log 'toSearch: ', toSearch if window.rocketDebug
+	return  not _.isEmpty(_.intersection(toFind, toSearch))
+
+all = (toFind, toSearch) ->
+	toFind = _.uniq(toFind)
+	toSearch = _.uniq(toSearch)
+	return _.isEmpty( _.difference( toFind, toSearch))
+
+Template.registerHelper 'hasPermission', (permission, scope) ->
+	unless _.isString( scope ) 
+		scope = Roles.GLOBAL_GROUP
+	return hasPermission( permission, scope, atLeastOne)
+
+RocketChat.authz.hasAllPermission = (permissions, scope=Roles.GLOBAL_GROUP) ->
+	return hasPermission( permissions, scope, all )
+
+RocketChat.authz.hasAtLeastOnePermission = (permissions, scope=Roles.GLOBAL_GROUP) ->
+	return hasPermission(permissions, scope, atLeastOne)
+
+hasPermission = (permissions, scope=Roles.GLOBAL_GROUP, strategy) ->
+	userId = Meteor.userId()
+
+	unless userId
+		return false
+
+	unless RocketChat.authz.subscription.ready()
+		return false
+
+	unless _.isArray(permissions)
+		permissions = [permissions]
+
+	roleNames = Roles.getRolesForUser(userId, scope) 
+
+	userPermissions = []
+	for roleName in roleNames
+		userPermissions = userPermissions.concat(_.pluck(ChatPermissions.find({roles : roleName }).fetch(), '_id'))
+
+	return strategy( permissions, userPermissions)
diff --git a/packages/rocketchat-authorization/client/hasRole.coffee b/packages/rocketchat-authorization/client/hasRole.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..f0a95261041ff651fd5d19e8827cb1e26f09443c
--- /dev/null
+++ b/packages/rocketchat-authorization/client/hasRole.coffee
@@ -0,0 +1,6 @@
+RocketChat.authz.hasRole = (userId, roleName, scope=Roles.GLOBAL_GROUP) ->
+	unless Meteor.userId()
+		return false
+
+	# per alanning:roles, returns true if user is in ANY roles
+	return Roles.userIsInRole(userId, [roleName], scope)
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/client/startup.coffee b/packages/rocketchat-authorization/client/startup.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..ded8f7799ffbee2cdf91b9c999ed3776a6484270
--- /dev/null
+++ b/packages/rocketchat-authorization/client/startup.coffee
@@ -0,0 +1,2 @@
+Meteor.startup ->
+	RocketChat.authz.subscription = Meteor.subscribe 'permissions'
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/lib/permissions.coffee b/packages/rocketchat-authorization/lib/permissions.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..b719f7f9ed648c4d5df0d16de2fd541787017d97
--- /dev/null
+++ b/packages/rocketchat-authorization/lib/permissions.coffee
@@ -0,0 +1 @@
+@ChatPermissions = new Meteor.Collection 'rocketchat_permissions'
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/lib/rocketchat.coffee b/packages/rocketchat-authorization/lib/rocketchat.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..a8c5e45883456f3e5154c9b4db8958ce845d9937
--- /dev/null
+++ b/packages/rocketchat-authorization/lib/rocketchat.coffee
@@ -0,0 +1 @@
+RocketChat.authz = {}
diff --git a/packages/rocketchat-authorization/package.js b/packages/rocketchat-authorization/package.js
new file mode 100644
index 0000000000000000000000000000000000000000..bb32b2ac371ef0fd28f8421991318a32a1b21f17
--- /dev/null
+++ b/packages/rocketchat-authorization/package.js
@@ -0,0 +1,37 @@
+Package.describe({
+  name: 'rocketchat:authorization',
+  version: '0.0.1',
+  summary: 'Role based authorization of actions',
+  git: '',
+  documentation: 'README.md'
+});
+
+Package.onUse(function(api) {
+  api.versionsFrom('1.0');
+  api.use([
+    'coffeescript',
+    'rocketchat:lib@0.0.1',
+    'alanning:roles@1.2.12'
+    ]);
+
+  api.use('templating', 'client');
+
+  api.addFiles('lib/permissions.coffee', ['server', 'client']);
+  api.addFiles('lib/rocketchat.coffee', ['server','client']);
+  api.addFiles('client/startup.coffee', ['client']);
+  api.addFiles('client/hasPermission.coffee', ['client']);
+  api.addFiles('client/hasRole.coffee', ['client']);
+
+
+  api.addFiles('server/functions/addUsersToRoles.coffee', ['server']);
+  api.addFiles('server/functions/getPermissionsForRole.coffee', ['server']);
+  api.addFiles('server/functions/getRoles.coffee', ['server']);
+  api.addFiles('server/functions/getRolesForUser.coffee', ['server']);
+  api.addFiles('server/functions/getUsersInRole.coffee', ['server']);
+  api.addFiles('server/functions/hasPermission.coffee', ['server']);
+  api.addFiles('server/functions/hasRole.coffee', ['server']);
+  api.addFiles('server/functions/removeUsersFromRoles.coffee', ['server']);
+
+  api.addFiles('server/publication.coffee', ['server']);
+  api.addFiles('server/startup.coffee', ['server']);
+});
diff --git a/packages/rocketchat-authorization/server/functions/addUsersToRoles.coffee b/packages/rocketchat-authorization/server/functions/addUsersToRoles.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..3b04cfa6fd5f82848a62d2fbe2dff8a5bf352d4a
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/addUsersToRoles.coffee
@@ -0,0 +1,26 @@
+RocketChat.authz.addUsersToRoles = (userIds, roleNames, scope ) ->
+	console.log '[methods] addUserToRoles -> '.green, 'arguments:', arguments
+	if not userIds or not roleNames
+		return false
+
+	unless _.isArray(userIds)
+		userIds = [userIds]
+
+	users = Meteor.users.find({_id: {$in : userIds}}).fetch()
+	unless userIds.length is users.length
+		throw new Meteor.Error 'invalid-user'
+
+	unless _.isArray(roleNames)
+		roleNames = [roleNames]
+
+	existingRoleNames = _.pluck(RocketChat.authz.getRoles().fetch(), 'name')
+	invalidRoleNames = _.difference( roleNames, existingRoleNames)
+	unless _.isEmpty(invalidRoleNames)
+		throw new Meteor.Error 'invalid-role'
+
+	unless _.isString(scope)
+		scope = Roles.GLOBAL_GROUP
+
+	Roles.addUsersToRoles( userIds, roleNames, scope)
+
+	return true
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/getPermissionsForRole.coffee b/packages/rocketchat-authorization/server/functions/getPermissionsForRole.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..f19203fe8c875a661059084b74c660b084c22504
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getPermissionsForRole.coffee
@@ -0,0 +1,9 @@
+RocketChat.authz.getPermissionsForRole = (roleName) ->
+	unless roleName
+		throw new Meteor.Error 'invalid-role'
+
+	roleNames = _.pluck(RocketChat.authz.getRoles().fetch(), 'name')
+	unless roleName in roleNames
+		throw new Meteor.Error 'invalid-role'
+
+	return _.pluck(ChatPermissions.find({roles : roleName }).fetch(), '_id')
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/getRoles.coffee b/packages/rocketchat-authorization/server/functions/getRoles.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..37c3d2537fdb438dcc9afc654e5eb1d941ef69af
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getRoles.coffee
@@ -0,0 +1,2 @@
+RocketChat.authz.getRoles = ->
+	return Roles.getAllRoles()
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/getRolesForUser.coffee b/packages/rocketchat-authorization/server/functions/getRolesForUser.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..40f8564a28eaf39aa1bc64178b7e0be4fa02b1cd
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getRolesForUser.coffee
@@ -0,0 +1,7 @@
+RocketChat.authz.getRolesForUser = (userId, scope) ->
+	console.log '[methods] getRolesForUser -> '.green, 'arguments:', arguments
+	# returns roles for the given scope as well as the global scope
+	unless scope
+		scope = Roles.GLOBAL_GROUP
+
+	return Roles.getRolesForUser(userId, scope) 
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee b/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..d5193830a0ad50ada1513624d1781479670c261d
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/getUsersInRole.coffee
@@ -0,0 +1,6 @@
+RocketChat.authz.getUsersInRole = (roleName, scope) ->
+	# alanning:roles doc says this is an expensive operation
+	unless _.isString(scope)
+		scope = Roles.GLOBAL_GROUP
+		
+	return Roles.getUsersInRole(roleName, scope)
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/hasPermission.coffee b/packages/rocketchat-authorization/server/functions/hasPermission.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..f0d2d3ca2e92327ddd41a49cf760d4a3806f9a56
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/hasPermission.coffee
@@ -0,0 +1,12 @@
+RocketChat.authz.hasPermission = (userId, permissionId, scope) ->
+	console.log '[methods] hasPermission -> '.green, 'arguments:', arguments
+
+	# get user's roles
+	roles = RocketChat.authz.getRolesForUser(userId, scope)
+
+	# get permissions for user's roles
+	permissions = []
+	for role in roles
+		permissions = permissions.concat( RocketChat.authz.getPermissionsForRole( role ))
+	# may contain duplicate, but doesn't matter
+	return permissionId in permissions
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/hasRole.coffee b/packages/rocketchat-authorization/server/functions/hasRole.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..83d32ea862a3000591167a5cefe5f1d1bcaf198c
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/hasRole.coffee
@@ -0,0 +1,4 @@
+RocketChat.authz.hasRole = (userId, roleName, scope) ->
+	console.log '[methods] hasRoles -> '.green, 'arguments:', arguments
+	# per alanning:roles, returns true if user is in ANY roles
+	return Roles.userIsInRole(userId, [roleName], scope)
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/functions/removeUsersFromRoles.coffee b/packages/rocketchat-authorization/server/functions/removeUsersFromRoles.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..a3f7c794d898a711815f3488eafae4f30b135248
--- /dev/null
+++ b/packages/rocketchat-authorization/server/functions/removeUsersFromRoles.coffee
@@ -0,0 +1,26 @@
+RocketChat.authz.removeUsersFromRoles = (userIds, roleNames, scope ) ->
+	console.log '[methods] removeUsersFromRoles -> '.green, 'arguments:', arguments
+	if not userIds or not roleNames
+		return false
+
+	unless _.isArray(userIds)
+		userIds = [userIds]
+
+	users = Meteor.users.find({_id: {$in : userIds}}).fetch()
+	unless userIds.length is users.length
+		throw new Meteor.Error 'invalid-user'
+
+	unless _.isArray(roleNames)
+		roleNames = [roleNames]
+
+	existingRoleNames = _.pluck(RocketChat.authz.getRoles().fetch(), 'name')
+	invalidRoleNames = _.difference( roleNames, existingRoleNames)
+	unless _.isEmpty(invalidRoleNames)
+		throw new Meteor.Error 'invalid-role'
+
+	unless _.isString(scope)
+		scope = Roles.GLOBAL_GROUP
+
+	Roles.removeUsersFromRoles( userIds, roleNames, scope)
+
+	return true
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/publication.coffee b/packages/rocketchat-authorization/server/publication.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..5cf4adef1df72ad69605fce232cd4328a3ef0034
--- /dev/null
+++ b/packages/rocketchat-authorization/server/publication.coffee
@@ -0,0 +1,3 @@
+Meteor.publish 'permissions', ->
+	console.log '[publish] permissions'.green
+	return ChatPermissions.find {} 
\ No newline at end of file
diff --git a/packages/rocketchat-authorization/server/startup.coffee b/packages/rocketchat-authorization/server/startup.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..9edeec2d97582b78fb11f5d6187d55606f05ba16
--- /dev/null
+++ b/packages/rocketchat-authorization/server/startup.coffee
@@ -0,0 +1,87 @@
+Meteor.startup ->
+
+	# Note:
+	# 1.if we need to create a role that can only edit channel message, but not edit group message
+	# then we can define edit-<type>-message instead of edit-message
+	# 2. admin, moderator, and user roles should not be deleted as they are referened in the code.
+	permissions = [
+
+		{ _id: 'view-statistics', 
+		roles : ['admin', 'temp-role']}
+
+		{ _id: 'view-privileged-setting', 
+		roles : ['admin']}
+
+		{ _id: 'edit-privileged-setting', 
+		roles : ['admin']}
+
+		{ _id: 'view-room-administration', 
+		roles : ['admin']}
+
+		{ _id: 'view-user-administration', 
+		roles : ['admin']}
+
+		{ _id: 'view-full-other-user-info', 
+		roles : ['admin']}
+
+		{ _id: 'edit-other-user-info', 
+		roles : ['admin']}
+
+		{ _id: 'assign-admin-role', 
+		roles : ['admin']}
+
+		{ _id: 'edit-other-user-active-status', 
+		roles : ['admin', 'site-moderator']}
+
+		{ _id: 'delete-user', 
+		roles : ['admin']}
+
+		{ _id: 'view-other-user-channels', 
+		roles : ['admin']}
+
+		{ _id: 'add-oath-service', 
+		roles : ['admin']}
+
+		{ _id: 'run-migration', 
+		roles : ['admin']}
+
+		{ _id: 'create-c', 
+		roles : ['admin', 'site-moderator', 'user']}
+
+		{ _id: 'delete-c', 
+		roles : ['admin', 'site-moderator']}
+
+		{ _id: 'edit-room', 
+		roles : ['admin', 'site-moderator', 'moderator']}
+
+		{ _id: 'edit-message', 
+		roles : ['admin', 'site-moderator', 'moderator']}
+
+		{ _id: 'delete-message', 
+		roles : ['admin', 'site-moderator', 'moderator']}
+
+		{ _id: 'ban-user', 
+		roles : ['admin', 'site-moderator', 'moderator']}
+
+		{ _id: 'create-p', 
+		roles : ['admin', 'site-moderator', 'user']}
+
+		{ _id: 'delete-p', 
+		roles : ['admin', 'site-moderator']}
+
+		{ _id: 'delete-d', 
+		roles : ['admin', 'site-moderator']}
+
+	]
+
+	#alanning:roles
+	roles = _.pluck(Roles.getAllRoles().fetch(), 'name');
+
+	for permission in permissions
+		ChatPermissions.upsert( permission._id, {$setOnInsert : permission })
+		for role in permission.roles
+			unless role in roles
+				Roles.createRole role
+				roles.push(role)
+
+
diff --git a/packages/rocketchat-lib/server/methods/setAdminStatus.coffee b/packages/rocketchat-lib/server/methods/setAdminStatus.coffee
index 6d2cdbb82ae68a8e403e24583f0543bfc01136d1..b81d6d9f04f62db1ee3817794d0afd9854d3f5c2 100644
--- a/packages/rocketchat-lib/server/methods/setAdminStatus.coffee
+++ b/packages/rocketchat-lib/server/methods/setAdminStatus.coffee
@@ -3,9 +3,12 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error 'invalid-user', "[methods] setAdminStatus -> Invalid user"
 
-		unless Meteor.user()?.admin is true
+		unless RocketChat.authz.hasPermission( Meteor.userId(), 'assign-admin-role') is true
 			throw new Meteor.Error 'not-authorized', '[methods] setAdminStatus -> Not authorized'
 
-		Meteor.users.update userId, { $set: { admin: admin } }
+		if admin
+			RocketChat.authz.addUsersToRoles( userId, 'admin')
+		else
+			RocketChat.authz.removeUsersFromRoles( userId, 'admin')
 
 		return true
diff --git a/packages/rocketchat-lib/server/methods/updateUser.coffee b/packages/rocketchat-lib/server/methods/updateUser.coffee
index 981560219a125aa698407a0e34ef72a911230e81..9a20d41012221417c70dc3176a562077088f4b80 100644
--- a/packages/rocketchat-lib/server/methods/updateUser.coffee
+++ b/packages/rocketchat-lib/server/methods/updateUser.coffee
@@ -7,7 +7,8 @@ Meteor.methods
 
 		user = Meteor.user()
 
-		if user._id isnt userData._id and user.admin isnt true
+		canEditUserPermission = RocketChat.authz.hasPermission( user._id, 'edit-other-user-info')
+		if user._id isnt userData._id and canEditUserPermission isnt true
 			throw new Meteor.Error 'not-authorized', '[methods] updateUser -> Not authorized'
 
 		unless userData._id
diff --git a/packages/rocketchat-lib/settings/server/addOAuthService.coffee b/packages/rocketchat-lib/settings/server/addOAuthService.coffee
index a90709bf36215f28e393b31a1668335d16e28633..8a42ff2df70c3fe6d317606803ac801b7a880bab 100644
--- a/packages/rocketchat-lib/settings/server/addOAuthService.coffee
+++ b/packages/rocketchat-lib/settings/server/addOAuthService.coffee
@@ -5,7 +5,7 @@ Meteor.methods
 
 		console.log '[methods] addOAuthService -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
-		unless Meteor.user()?.admin is true
+		unless RocketChat.authz.hasALeastOnePermission( Meteor.userId(), 'add-oath-service') is true
 			throw new Meteor.Error 'not-authorized', '[methods] addOAuthService -> Not authorized'
 
 		name = s.capitalize(name)
diff --git a/packages/rocketchat-lib/settings/server/methods.coffee b/packages/rocketchat-lib/settings/server/methods.coffee
index 0808f9582f1dba57e7759c57329ea193b467fd62..cf19272c96b47a32490bfd52db54df3831110f13 100644
--- a/packages/rocketchat-lib/settings/server/methods.coffee
+++ b/packages/rocketchat-lib/settings/server/methods.coffee
@@ -50,7 +50,7 @@ Meteor.methods
 		if Meteor.userId()?
 			user = Meteor.users.findOne Meteor.userId()
 		
-		unless user?.admin is true
+		unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-privileged-setting') is true
 			throw new Meteor.Error 503, 'Not authorized'
 
 		# console.log "saveSetting -> ".green, _id, value
diff --git a/packages/rocketchat-lib/settings/server/publication.coffee b/packages/rocketchat-lib/settings/server/publication.coffee
index 83a8ed6d967a77957c9abfe41358a89390f74eee..92dab9b981ac925e3bbe73bd95b775acfc99cca5 100644
--- a/packages/rocketchat-lib/settings/server/publication.coffee
+++ b/packages/rocketchat-lib/settings/server/publication.coffee
@@ -8,8 +8,7 @@ Meteor.publish 'admin-settings', ->
 	unless @userId
 		return @ready()
 
-	user = Meteor.users.findOne @userId
-	if user.admin
+	if RocketChat.authz.hasPermission( @userId, 'view-privileged-setting')
 		return Settings.find()
 	else
 		return @ready()
diff --git a/packages/rocketchat-statistics/server/methods/getStatistics.coffee b/packages/rocketchat-statistics/server/methods/getStatistics.coffee
index dde2b348a103da856a059c549de8ff860e86b08e..8bf3e8cb1d915b244f6eab3f68d2be6f6361b66a 100644
--- a/packages/rocketchat-statistics/server/methods/getStatistics.coffee
+++ b/packages/rocketchat-statistics/server/methods/getStatistics.coffee
@@ -5,7 +5,7 @@ Meteor.methods
 
 		console.log '[methods] getStatistics -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
-		unless Meteor.user()?.admin is true
+		unless RocketChat.authz.hasPermission(Meteor.userId(), 'view-statistics') is true
 			throw new Meteor.Error 'not-authorized', '[methods] getStatistics -> Not authorized'
 
 		return RocketChat.statistics.get()
\ No newline at end of file
diff --git a/server/lib/accounts.coffee b/server/lib/accounts.coffee
index 809a70ac490605f53b3bcd67ca6bbff57d0c9f71..bf6b440764b75ab31640f0ff71ce5441feab152f 100644
--- a/server/lib/accounts.coffee
+++ b/server/lib/accounts.coffee
@@ -24,9 +24,8 @@ Accounts.onCreateUser (options, user) ->
 	user.status = 'offline'
 	user.active = not RocketChat.settings.get 'Accounts_ManuallyApproveNewUsers'
 
-	# when inserting first user, set admin: true
-	unless RocketChat.models.Users.findOne()
-		user.admin = true
+	# when inserting first user give them admin privileges otherwise make a regular user
+	roleName = if RocketChat.models.Users.findOne() then 'user' else 'admin'
 
 	if not user?.name? or user.name is ''
 		if options.profile?.name?
@@ -47,6 +46,9 @@ Accounts.onCreateUser (options, user) ->
 				]
 
 	Meteor.defer ->
+		# need to defer role assignment because underlying alanning:roles requires user
+		# to exist in users collection
+		RocketChat.authz.addUsersToRoles( user._id, roleName)
 		RocketChat.callbacks.run 'afterCreateUser', options, user
 
 	return user
diff --git a/server/methods/createChannel.coffee b/server/methods/createChannel.coffee
index 283fb8ec64c16a8a6fc84171935417a840f99f3a..2867d975b6ce6e997e311bd682ba87ff53951dc9 100644
--- a/server/methods/createChannel.coffee
+++ b/server/methods/createChannel.coffee
@@ -6,6 +6,9 @@ Meteor.methods
 		if not /^[0-9a-z-_]+$/.test name
 			throw new Meteor.Error 'name-invalid'
 
+		if RocketChat.authz.hasPermission(Meteor.userId(), 'create-c') isnt true
+			throw new Meteor.Error 'not-authorized', '[methods] createChannel -> Not authorized'
+
 		console.log '[methods] createChannel -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
 		now = new Date()
@@ -33,6 +36,8 @@ Meteor.methods
 
 		# create new room
 		rid = ChatRoom.insert room
+		# set creator as channel moderator.  permission limited to channel by scoping to rid
+		RocketChat.authz.addUsersToRoles(Meteor.userId(), 'moderator', rid)
 
 		for username in members
 			member = RocketChat.models.Users.findOneByUsername username
diff --git a/server/methods/createPrivateGroup.coffee b/server/methods/createPrivateGroup.coffee
index 5b741e42afb37659c0d4206f3617650383e67f99..e055382e5a2e46d4e17b7d41c1f44b99087bc60f 100644
--- a/server/methods/createPrivateGroup.coffee
+++ b/server/methods/createPrivateGroup.coffee
@@ -3,6 +3,9 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error 'invalid-user', "[methods] createPrivateGroup -> Invalid user"
 
+		unless RocketChat.authz.hasPermission(Meteor.userId(), 'create-p') 
+			throw new Meteor.Error 'not-authorized', '[methods] createPrivateGroup -> Not authorized'
+
 		console.log '[methods] createPrivateGroup -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
 		if not /^[0-9a-z-_]+$/.test name
@@ -31,6 +34,9 @@ Meteor.methods
 			name: name
 			msgs: 0
 
+		# set creator as group moderator.  permission limited to group by scoping to rid
+		RocketChat.authz.addUsersToRoles(Meteor.userId(), 'moderator', rid)
+
 		for username in members
 			member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }})
 			if not member?
diff --git a/server/methods/deleteMessage.coffee b/server/methods/deleteMessage.coffee
index e18e4d7a27ae6390646360ee38a6f407b3a99b1b..8a9288b437c74f29544f4f07a6558d5ca486a02d 100644
--- a/server/methods/deleteMessage.coffee
+++ b/server/methods/deleteMessage.coffee
@@ -3,13 +3,17 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error('invalid-user', "[methods] deleteMessage -> Invalid user")
 
-		if not RocketChat.settings.get 'Message_AllowDeleting'
-			throw new Meteor.Error 'message-deleting-not-allowed', "[methods] updateMessage -> Message deleting not allowed"
+		originalMessage = ChatMessage.findOne message._id, {fields: {u: 1, rid: 1}}
+		if not originalMessage?
+			throw new Meteor.Error 'message-deleting-not-allowed', "[methods] deleteMessage -> Message with id [#{message._id} dos not exists]"
 
-		user = RocketChat.models.Users.findOneById Meteor.userId()
+		hasPermission = RocketChat.authz.hasPermission(Meteor.userId(), 'delete-message', originalMessage.rid)
+		deleteAllowed = RocketChat.settings.get 'Message_AllowDeleting'
 
-		unless user?.admin is true or message.u._id is Meteor.userId()
-			throw new Meteor.Error 'not-authorized', '[methods] deleteMessage -> Not authorized'
+		deleteOwn = originalMessage?.u?._id is Meteor.userId()
+
+		unless hasPermission or (deleteAllowed and deleteOwn)
+			throw new Meteor.Error 'message-deleting-not-allowed', "[methods] deleteMessage -> Message deleting not allowed"
 
 		console.log '[methods] deleteMessage -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
@@ -17,12 +21,11 @@ Meteor.methods
 		showDeletedStatus = RocketChat.settings.get 'Message_ShowDeletedStatus'
 
 		deleteQuery =
-			_id: message._id
-		deleteQuery['u._id'] = Meteor.userId() if user?.admin isnt true
+			_id: originalMessage._id
 
 		if keepHistory
 			if showDeletedStatus
-				history = ChatMessage.findOne message._id
+				history = ChatMessage.findOne originalMessage._id
 				history._hidden = true
 				history.parent = history._id
 				history.ets = new Date()
@@ -44,4 +47,4 @@ Meteor.methods
 					t: 'rm'
 					ets: new Date()
 		else
-			RocketChat.Notifications.notifyRoom message.rid, 'deleteMessage', { _id: message._id }
+			RocketChat.Notifications.notifyRoom originalMessage.rid, 'deleteMessage', { _id: originalMessage._id }
diff --git a/server/methods/deleteUser.coffee b/server/methods/deleteUser.coffee
index 0a0dc948f3cec7b7b1f67fa66e674b3aaeae796f..e678b04a752e7f3753ac0530aa11edc74b855f51 100644
--- a/server/methods/deleteUser.coffee
+++ b/server/methods/deleteUser.coffee
@@ -4,7 +4,8 @@ Meteor.methods
 			throw new Meteor.Error('invalid-user', "[methods] deleteUser -> Invalid user")
 
 		user = RocketChat.models.Users.findOneById Meteor.userId()
-		unless user?.admin is true
+
+		unless RocketChat.authz.hasPermission(Meteor.userId(), 'delete-user') is true
 			throw new Meteor.Error 'not-authorized', '[methods] deleteUser -> Not authorized'
 
 		user = RocketChat.models.Users.findOneById userId
diff --git a/server/methods/eraseRoom.coffee b/server/methods/eraseRoom.coffee
index 90881984d009bfdd5469cdfbad88bbb800f44178..d1de6d3e7f05e06cdaf17845ede7722cb2948899 100644
--- a/server/methods/eraseRoom.coffee
+++ b/server/methods/eraseRoom.coffee
@@ -2,10 +2,9 @@ Meteor.methods
 	eraseRoom: (rid) ->
 		fromId = Meteor.userId()
 
-		user = RocketChat.models.Users.findOneById Meteor.userId()
-		if user.admin is true
-
+		roomType = ChatRoom.findOne(rid)?.t
 
+		if RocketChat.authz.hasPermission( fromId, "delete-#{roomType}", rid )
 			# console.log '[methods] eraseRoom -> '.green, 'fromId:', fromId, 'rid:', rid
 
 			# ChatRoom.update({ _id: rid}, {'$pull': { userWatching: Meteor.userId(), userIn: Meteor.userId() }})
@@ -14,3 +13,5 @@ Meteor.methods
 			ChatSubscription.remove({rid: rid})
 			ChatRoom.remove(rid)
 			# @TODO remove das mensagens lidas do usuário
+		else
+			throw new Meteor.Error 'unauthorized'
diff --git a/server/methods/migrate.coffee b/server/methods/migrate.coffee
index 056eac9f4af0bd47ababf5a64cece83d135d64f8..915b4582f37ac9de86dd7a76f8c332ef4ef56917 100644
--- a/server/methods/migrate.coffee
+++ b/server/methods/migrate.coffee
@@ -2,7 +2,8 @@ Meteor.methods
 	migrateTo: (version) ->
 		user = Meteor.user()
 
-		if not user? or user.admin isnt true
+		if not user? or RocketChat.authz.hasPermission(user._id, 'run-migration') isnt true
+			console.log '[methods] createChannel -> Not authorized'
 			return
 
 		this.unblock()
diff --git a/server/methods/removeUserFromRoom.coffee b/server/methods/removeUserFromRoom.coffee
index eee2536e70b5dedae63f2f43cd57037655773c3b..8500ff030649f5365176b7147c41225baf3021ff 100644
--- a/server/methods/removeUserFromRoom.coffee
+++ b/server/methods/removeUserFromRoom.coffee
@@ -18,6 +18,12 @@ Meteor.methods
 
 		ChatSubscription.remove { 'u._id': data.username, rid: data.rid }
 
+		switch room.t
+			when 'c'
+				RocketChat.authz.removeUsersFromRole(removedUser._id; 'channel-moderator',  data.rid)
+			when 'p'
+				RocketChat.authz.removeUsersFromRole(removedUser._id; 'group-moderator',  data.rid)
+
 		ChatMessage.insert
 			rid: data.rid
 			ts: (new Date)
diff --git a/server/methods/saveRoomName.coffee b/server/methods/saveRoomName.coffee
index be073725c466cfb9275c4d1449b6f44cc054616e..23de97d60d5fc9cbaee0faaacdd27278345a95d4 100644
--- a/server/methods/saveRoomName.coffee
+++ b/server/methods/saveRoomName.coffee
@@ -5,7 +5,11 @@ Meteor.methods
 
 		room = ChatRoom.findOne rid
 
-		if room.u._id isnt Meteor.userId() or room.t not in ['c', 'p']
+		if room.t not in ['c', 'p']
+			throw new Meteor.Error 403, 'Not allowed'
+
+		unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)
+		#if room.u._id isnt Meteor.userId() and not hasPermission 
 			throw new Meteor.Error 403, 'Not allowed'
 
 		if not /^[0-9a-z-_]+$/.test name
diff --git a/server/methods/setUserActiveStatus.coffee b/server/methods/setUserActiveStatus.coffee
index 59e4dd268c3d62fdd09d7e878e01bc83c48f4ceb..f7084ae499fc67eee8238d4cbbd3a255259e5726 100644
--- a/server/methods/setUserActiveStatus.coffee
+++ b/server/methods/setUserActiveStatus.coffee
@@ -3,8 +3,7 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error 'invalid-user', '[methods] setUserActiveStatus -> Invalid user'
 
-		user = RocketChat.models.Users.findOneById Meteor.userId()
-		unless user?.admin is true
+		unless RocketChat.authz.hasPermission( Meteor.userId(), 'edit-other-user-active-status') is true
 			throw new Meteor.Error 'not-authorized', '[methods] setUserActiveStatus -> Not authorized'
 
 		RocketChat.models.Users.setUserActive userId, active
diff --git a/server/methods/updateMessage.coffee b/server/methods/updateMessage.coffee
index 73d884f614d7c81f2f6d786ff4e9306f3508b2fd..65e3332e3ae4136cfbd38448d05a93cb2cb7044e 100644
--- a/server/methods/updateMessage.coffee
+++ b/server/methods/updateMessage.coffee
@@ -3,15 +3,14 @@ Meteor.methods
 		if not Meteor.userId()
 			throw new Meteor.Error('invalid-user', "[methods] updateMessage -> Invalid user")
 
-		if not RocketChat.settings.get 'Message_AllowEditing'
-			throw new Meteor.Error 'message-editing-not-allowed', "[methods] updateMessage -> Message editing not allowed"
-
-		user = RocketChat.models.Users.findOneById Meteor.userId()
-
 		originalMessage = ChatMessage.findOne message._id
 
-		unless user?.admin is true or originalMessage?.u?._id is Meteor.userId()
-			throw new Meteor.Error 'not-authorized', '[methods] updateMessage -> Not authorized'
+		hasPermission = RocketChat.authz.hasPermission(Meteor.userId(), 'edit-message', message.rid)
+		editAllowed = RocketChat.settings.get 'Message_AllowEditing'
+		editOwn = originalMessage?.u?._id is Meteor.userId()
+
+		unless hasPermission or (editAllowed and editOwn)
+			throw new Meteor.Error 'message-editing-not-allowed', "[methods] updateMessage -> Message editing not allowed"
 
 		console.log '[methods] updateMessage -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments
 
@@ -35,9 +34,9 @@ Meteor.methods
 
 		ChatMessage.update
 			_id: tempid
-			'u._id': Meteor.userId()
 		,
 			$set: message
 
 		# Meteor.defer ->
 		# 	RocketChat.callbacks.run 'afterSaveMessage', ChatMessage.findOne(message.id)
+
diff --git a/server/publications/adminRooms.coffee b/server/publications/adminRooms.coffee
index 6a0e0e32a1031d60fee7978bb49bd48e1dd8a723..6d02cb7fcfbd7fd10ef195476dc5ab37775a0900 100644
--- a/server/publications/adminRooms.coffee
+++ b/server/publications/adminRooms.coffee
@@ -2,8 +2,7 @@ Meteor.publish 'adminRooms', (filter, types, limit) ->
 	unless this.userId
 		return this.ready()
 
-	user = RocketChat.models.Users.findOneById this.userId
-	if user.admin isnt true
+	if RocketChat.authz.hasPermission(@userId, 'view-room-administration') isnt true
 		return this.ready()
 
 	unless _.isArray types
diff --git a/server/publications/fullUserData.coffee b/server/publications/fullUserData.coffee
index 5683f5537584df2fe58e3eee41012428f3ee8622..36949ab9142da784cc7b43321e09c4302227d1f1 100644
--- a/server/publications/fullUserData.coffee
+++ b/server/publications/fullUserData.coffee
@@ -10,16 +10,16 @@ Meteor.publish 'fullUserData', (filter, limit) ->
 		status: 1
 		utcOffset: 1
 
-	if user.admin is true
+	if RocketChat.authz.hasPermission( @userId, 'view-full-other-user-info') is true
 		fields = _.extend fields,
 			emails: 1
 			phone: 1
 			statusConnection: 1
-			admin: 1
 			createdAt: 1
 			lastLogin: 1
 			active: 1
 			services: 1
+			roles : 1
 	else
 		limit = 1
 
diff --git a/server/publications/userChannels.coffee b/server/publications/userChannels.coffee
index d6ba81b346007d0571bb5cd062ae26eae523208a..51fcf4ab09bfdc42f8a7578a9258d882e85128d4 100644
--- a/server/publications/userChannels.coffee
+++ b/server/publications/userChannels.coffee
@@ -2,8 +2,7 @@ Meteor.publish 'userChannels', (userId) ->
 	unless this.userId
 		return this.ready()
 
-	user = RocketChat.models.Users.findOneById this.userId
-	if user.admin isnt true
+	if RocketChat.authz.hasPermission( @userId, 'view-other-user-channels') isnt true
 		return this.ready()
 
 	query = { "u._id": userId }
diff --git a/server/publications/userData.coffee b/server/publications/userData.coffee
index ba4a8c9a36df71b5a7e358ebfbf30cc8a8e91853..3d7811c9f40bf6c0a7f2aefd578607a262629809 100644
--- a/server/publications/userData.coffee
+++ b/server/publications/userData.coffee
@@ -12,7 +12,6 @@ Meteor.publish 'userData', ->
 			statusDefault: 1
 			statusConnection: 1
 			avatarOrigin: 1
-			admin: 1
 			utcOffset: 1
 			language: 1
 			settings: 1
diff --git a/server/startup/initialData.coffee b/server/startup/initialData.coffee
index dd04fd9504c75e3d5006392e49ab78111e3d86c1..0bd2da0513adc26d68ab04b89970c79dfd569770 100644
--- a/server/startup/initialData.coffee
+++ b/server/startup/initialData.coffee
@@ -19,7 +19,7 @@ Meteor.startup ->
 		if process.env.ADMIN_EMAIL? and process.env.ADMIN_PASS?
 			re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i
 			if re.test process.env.ADMIN_EMAIL
-				if not RocketChat.models.Users.findOneAdmin(true)?
+				if _.isEmpty(RocketChat.authz.getUsersInRole( 'admin' ).fetch())
 					if not RocketChat.models.Users.findOneByEmailAddress process.env.ADMIN_EMAIL
 						console.log 'Inserting admin user'.red
 						console.log "email: #{process.env.ADMIN_EMAIL} | password: #{process.env.ADMIN_PASS}".red
@@ -30,9 +30,10 @@ Meteor.startup ->
 								verified: true
 							],
 							name: 'Admin'
-							admin: true
 
 						Accounts.setPassword id, process.env.ADMIN_PASS
+						RocketChat.authz.addUsersToRoles( id, 'admin')
+
 					else
 						console.log 'E-mail exists; ignoring environment variables ADMIN_EMAIL and ADMIN_PASS'.red
 				else
@@ -41,10 +42,9 @@ Meteor.startup ->
 				console.log 'E-mail provided is invalid; ignoring environment variables ADMIN_EMAIL and ADMIN_PASS'.red
 
 		# Set oldest user as admin, if none exists yet
-		admin = RocketChat.models.Users.findOneAdmin true, { fields: { _id: 1 } }
-		unless admin
+		if _.isEmpty( RocketChat.authz.getUsersInRole( 'admin' ).fetch())
 			# get oldest user
 			oldestUser = RocketChat.models.Users.findOne({}, { fields: { username: 1 }, sort: {createdAt: 1}})
 			if oldestUser
-				Meteor.users.update {_id: oldestUser._id}, {$set: {admin: true}}
+				RocketChat.authz.addUsersToRoles( oldestUser._id, 'admin')
 				console.log "No admins are found. Set #{oldestUser.username} as admin for being the oldest user"
diff --git a/server/startup/migrations/v19.coffee b/server/startup/migrations/v19.coffee
new file mode 100644
index 0000000000000000000000000000000000000000..02c47df293c6cc7b701a0773ffaa782a85f372b2
--- /dev/null
+++ b/server/startup/migrations/v19.coffee
@@ -0,0 +1,28 @@
+Meteor.startup ->
+	Migrations.add
+		version: 19
+		up: ->
+			###
+			# Migrate existing admin users to Role based admin functionality
+			# 'admin' role applies to global scope
+			###
+			admins = Meteor.users.find({ admin: true }, { fields: { _id: 1, username:1 } }).fetch()
+			RocketChat.authz.addUsersToRoles( _.pluck(admins, '_id'), ['admin'])
+			Meteor.users.update({}, { $unset :{admin:''}}, {multi:true})
+			usernames = _.pluck( admins, 'username').join(', ')
+			console.log "Migrate #{usernames} from admin field to 'admin' role".green
+
+			# Add 'user' role to all users
+			users = Meteor.users.find().fetch()
+			RocketChat.authz.addUsersToRoles( _.pluck(users, '_id'), ['user'])
+			usernames = _.pluck( users, 'username').join(', ')
+			console.log "Add #{usernames} to 'user' role".green
+
+			# Add 'moderator' role to channel/group creators 
+			rooms = ChatRoom.find({t: {$in : ['c','p']}}).fetch()
+			_.each( rooms, (room) -> 
+				creator = room?.u?._id
+				if creator
+					RocketChat.authz.addUsersToRoles( creator, ['moderator'], room._id)
+					console.log "Add #{room.u.username} to 'moderator' role".green
+				)