From fa7c87ec5b8ed42ba5b813e06bf3c464548809da Mon Sep 17 00:00:00 2001
From: Diego Sampaio <chinello@gmail.com>
Date: Mon, 31 Aug 2015 15:43:58 -0300
Subject: [PATCH] guest users

---
 .meteor/packages                              |   4 +-
 .meteor/versions                              |   1 +
 lib/guests.coffee                             |   2 +
 .../lib/{visitor.coffee => _visitor.coffee}   |   0
 .../app/client/lib/chatMessages.coffee        |  43 ++--
 .../app/client/lib/guests.coffee              |   3 +
 .../app/client/lib/msgTyping.coffee           |  70 ++++++
 .../app/client/stylesheets/_variables.less    |  30 +++
 .../app/client/stylesheets/main.less          | 210 +++++++++++++++++-
 .../app/client/views/room.html                |  18 +-
 packages/rocketchat-external/app/run.sh       |   4 +-
 packages/rocketchat-external/guests.coffee    |   3 +
 packages/rocketchat-external/methods.coffee   |  78 ++++---
 packages/rocketchat-external/package.js       |   5 +-
 server/lib/accounts.coffee                    |   7 +
 15 files changed, 411 insertions(+), 67 deletions(-)
 create mode 100644 lib/guests.coffee
 rename packages/rocketchat-external/app/client/lib/{visitor.coffee => _visitor.coffee} (100%)
 create mode 100644 packages/rocketchat-external/app/client/lib/guests.coffee
 create mode 100644 packages/rocketchat-external/app/client/lib/msgTyping.coffee
 create mode 100644 packages/rocketchat-external/app/client/stylesheets/_variables.less
 create mode 100644 packages/rocketchat-external/guests.coffee

diff --git a/.meteor/packages b/.meteor/packages
index 1e89307d3bf..5beadf49fb1 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -19,6 +19,7 @@ meteor-platform
 reactive-dict
 reactive-var
 service-configuration
+artwells:accounts-guest
 
 arunoda:streams
 rocketchat:lib
@@ -35,7 +36,7 @@ rocketchat:me
 rocketchat:mentions
 rocketchat:oembed
 rocketchat:webrtc
-#rocketchat:external
+rocketchat:external
 #rocketchat:hubot
 #rocketchat:irc
 
@@ -81,4 +82,3 @@ monbro:mongodb-mapreduce-aggregation
 accounts-gitlab
 gitlab
 rocketchat:gitlab
-rocketchat:external
diff --git a/.meteor/versions b/.meteor/versions
index 1d24019ea92..12fe2744848 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -8,6 +8,7 @@ accounts-oauth@1.1.5
 accounts-password@1.1.1
 accounts-twitter@1.0.4
 aldeed:simple-schema@1.3.3
+artwells:accounts-guest@0.1.12
 arunoda:streams@0.1.17
 autoupdate@1.2.1
 base64@1.0.3
diff --git a/lib/guests.coffee b/lib/guests.coffee
new file mode 100644
index 00000000000..8e7fab0164c
--- /dev/null
+++ b/lib/guests.coffee
@@ -0,0 +1,2 @@
+console.log 'setting up guests'
+AccountsGuest.forced = false
diff --git a/packages/rocketchat-external/app/client/lib/visitor.coffee b/packages/rocketchat-external/app/client/lib/_visitor.coffee
similarity index 100%
rename from packages/rocketchat-external/app/client/lib/visitor.coffee
rename to packages/rocketchat-external/app/client/lib/_visitor.coffee
diff --git a/packages/rocketchat-external/app/client/lib/chatMessages.coffee b/packages/rocketchat-external/app/client/lib/chatMessages.coffee
index 72e27b71f68..03c026e82c6 100644
--- a/packages/rocketchat-external/app/client/lib/chatMessages.coffee
+++ b/packages/rocketchat-external/app/client/lib/chatMessages.coffee
@@ -73,19 +73,29 @@ class @ChatMessages
 			msg = input.value
 			input.value = ''
 			rid ?= visitor.getRoom(true)
-			msgObject = { _id: Random.id(), rid: rid, token: visitor.getToken(), msg: msg}
-			# this.stopTyping(rid)
-			#Check if message starts with /command
-			if msg[0] is '/'
-				match = msg.match(/^\/([^\s]+)(?:\s+(.*))?$/m)
-				if(match?)
-					command = match[1]
-					param = match[2]
-					Meteor.call 'slashCommand', {cmd: command, params: param, msg: msgObject }
+
+			sendMessage = ->
+				msgObject = { _id: Random.id(), rid: rid, msg: msg, token: visitor.getToken() }
+				MsgTyping.stop(rid)
+				#Check if message starts with /command
+				if msg[0] is '/'
+					match = msg.match(/^\/([^\s]+)(?:\s+(.*))?$/m)
+					if(match?)
+						command = match[1]
+						param = match[2]
+						Meteor.call 'slashCommand', {cmd: command, params: param, msg: msgObject }
+				else
+					#Run to allow local encryption
+					Meteor.call 'onClientBeforeSendMessage', {}
+					Meteor.call 'sendMessageExternal', msgObject
+
+			if not Meteor.userId()
+				Meteor.loginVisitor null, (error) ->
+					if not error
+						console.log 'usuario logado, mandanndo mensagem'
+						sendMessage()
 			else
-				#Run to allow local encryption
-				#Meteor.call 'onClientBeforeSendMessage', {}
-				Meteor.call 'sendMessageExternal', msgObject
+				sendMessage()
 
 	deleteMsg: (message) ->
 		Meteor.call 'deleteMessage', message, (error, result) ->
@@ -97,7 +107,7 @@ class @ChatMessages
 			msg = input.value
 			Meteor.call 'updateMessage', { id: id, msg: msg }
 			this.clearEditing()
-			# this.stopTyping(rid)
+			MsgTyping.stop(rid)
 
 	startTyping: (rid, input) ->
 		if _.trim(input.value) isnt ''
@@ -105,9 +115,6 @@ class @ChatMessages
 		else
 			MsgTyping.stop(rid)
 
-	stopTyping: (rid) ->
-		MsgTyping.stop(rid)
-
 	bindEvents: ->
 		if this.wrapper?.length
 			$(".input-message").autogrow
@@ -148,8 +155,8 @@ class @ChatMessages
 		keyCodes.push i for i in [35..40] # Home, End, Arrow Keys
 		keyCodes.push i for i in [112..123] # F1 - F12
 
-		# unless k in keyCodes
-		# 	this.startTyping(rid, input)
+		unless k in keyCodes
+			this.startTyping(rid, input)
 
 	keydown: (rid, event) ->
 		input = event.currentTarget
diff --git a/packages/rocketchat-external/app/client/lib/guests.coffee b/packages/rocketchat-external/app/client/lib/guests.coffee
new file mode 100644
index 00000000000..50b6afbda30
--- /dev/null
+++ b/packages/rocketchat-external/app/client/lib/guests.coffee
@@ -0,0 +1,3 @@
+console.log 'setting up guests'
+AccountsGuest.name = true
+AccountsGuest.forced = false
diff --git a/packages/rocketchat-external/app/client/lib/msgTyping.coffee b/packages/rocketchat-external/app/client/lib/msgTyping.coffee
new file mode 100644
index 00000000000..2de805e49af
--- /dev/null
+++ b/packages/rocketchat-external/app/client/lib/msgTyping.coffee
@@ -0,0 +1,70 @@
+@MsgTyping = do ->
+	stream = new Meteor.Stream 'typing'
+	timeout = 15000
+	timeouts = {}
+	renew = true
+	renewTimeout = 10000
+	selfTyping = new ReactiveVar false
+	usersTyping = {}
+	dep = new Tracker.Dependency
+
+	addStream = (room) ->
+		if _.isEmpty usersTyping[room]?.users
+			usersTyping[room] = { users: {} }
+			stream.on room, (typing) ->
+				unless typing?.username is Meteor.user()?.username
+					if typing.start
+						users = usersTyping[room].users
+						users[typing.username] = Meteor.setTimeout ->
+							delete users[typing.username]
+							usersTyping[room].users = users
+							dep.changed()
+						, timeout
+						usersTyping[room].users = users
+						dep.changed()
+					else if typing.stop
+						users = usersTyping[room].users
+						delete users[typing.username]
+						usersTyping[room].users = users
+						dep.changed()
+
+	Tracker.autorun ->
+		if visitor.getRoom()
+			addStream visitor.getRoom()
+
+	start = (room) ->
+		return unless renew
+
+		setTimeout ->
+			renew = true
+		, renewTimeout
+
+		renew = false
+		selfTyping.set true
+		stream.emit 'typing', { room: room, username: Meteor.user()?.username, start: true }
+		clearTimeout timeouts[room]
+		timeouts[room] = Meteor.setTimeout ->
+			stop(room)
+		, timeout
+
+	stop = (room) ->
+		renew = true
+		selfTyping.set false
+		if timeouts?[room]?
+			clearTimeout(timeouts[room])
+			timeouts[room] = null
+		stream.emit 'typing', { room: room, username: Meteor.user()?.username, stop: true }
+
+	get = (room) ->
+		dep.depend()
+		unless usersTyping[room]
+			usersTyping[room] = { users: {} }
+		users = usersTyping[room].users
+		return _.keys(users) or []
+
+	return {
+		start: start
+		stop: stop
+		get: get
+		selfTyping: selfTyping
+	}
diff --git a/packages/rocketchat-external/app/client/stylesheets/_variables.less b/packages/rocketchat-external/app/client/stylesheets/_variables.less
new file mode 100644
index 00000000000..c8bf1d2587a
--- /dev/null
+++ b/packages/rocketchat-external/app/client/stylesheets/_variables.less
@@ -0,0 +1,30 @@
+@header-min-height: 60px;
+@footer-min-height: 70px;
+
+@rooms-box-width: 260px;
+@flex-tab-width: 400px;
+@flex-tab-webrtc-width: 400px;
+@flex-tab-webrtc-2-width: 850px;
+
+// Colors
+// --------------
+
+//@primary-background-color: #045080;
+//@primary-background-color: #38393d;
+
+@primary-background-color: #04436a;
+@secondary-background-color: #F4F4F4;
+@tertiary-background-color: #EAEAEA;
+
+@link-font-color: #008CE3;
+
+@primary-font-color: #444444;
+@secondary-font-color: #7f7f7f;
+@tertiary-font-color: rgba(255, 255, 255, 0.6);
+@quaternary-font-color: rgba(255, 255, 255, 0.85);
+@info-font-color: #AAAAAA;
+
+@status-online: #35AC19;
+@status-offline: rgba(150, 150, 150, 0.50);
+@status-busy: #D30230;
+@status-away: #fcb316;
diff --git a/packages/rocketchat-external/app/client/stylesheets/main.less b/packages/rocketchat-external/app/client/stylesheets/main.less
index fc874885348..6f48fb6554a 100644
--- a/packages/rocketchat-external/app/client/stylesheets/main.less
+++ b/packages/rocketchat-external/app/client/stylesheets/main.less
@@ -1,6 +1,15 @@
+@import "_variables.less";
+
+* {
+	box-sizing: border-box;
+	-moz-box-sizing: border-box;
+	-webkit-box-sizing: border-box;
+}
 body {
 	padding: 0;
 	margin: 0;
+	font-family: sans-serif;
+	font-size: 10pt;
 }
 .external-room {
 	position: fixed;
@@ -8,25 +17,216 @@ body {
 	bottom: 0;
 	background-color: blue;
 	.title {
-		background-color: green;
+		background-color: #04436a;
+		color: #FFF;
 		position: fixed;
 		top: 0;
 		width: 100%;
 		height: 60px;
+		h1 {
+			line-height: 60px;
+			margin: 0;
+			padding: 0;
+			li {
+				padding: 0;
+			}
+		}
 	}
-	.wrapper {
-		background-color: purple;
+	.messages {
+		background-color: #FFF;
 		top: 60px;
 		bottom: 60px;
 		position: fixed;
 		width: 100%;
-		overflow-y: auto;
+		.wrapper {
+			overflow-y: auto;
+
+			ul {
+				list-style-type: none;
+				padding: 0;
+				li {
+					padding: 0;
+				}
+			}
+
+			.message {
+				font-size: 14px;
+				padding-left: 50px;
+				position: relative;
+				line-height: 20px;
+				margin: 12px 20px 5px;
+				margin-top: 12px;
+				min-height: 40px;
+				&:nth-child(1) {
+					margin-top: 0;
+				}
+				&.new-day {
+					margin-top: 60px;
+				}
+				&.new-day {
+					&:before {
+						content: attr(data-date);
+						display: block;
+						position: absolute;
+						top: -30px;
+						left: 0;
+						font-size: 12px;
+						font-weight: 600;
+						text-align: center;
+						left: -webkit-calc(~'50% - 70px');
+						left: -moz-calc(~'50% - 70px');
+						left: calc(~'50% - 70px');
+						color: @secondary-font-color;
+						z-index: 10;
+						padding: 0 10px;
+						background-color: #FFF;
+						min-width: 140px;
+					}
+					&:after {
+						content: " ";
+						display: block;
+						position: absolute;
+						top: -20px;
+						left: 0;
+						width: 100%;
+						border-top: 1px solid #ddd;
+					}
+				}
+				.edit-message {
+					display: none;
+					cursor: pointer;
+				}
+				&.own:hover:not(.system) .edit-message {
+					display: inline-block;
+				}
+				.delete-message {
+					display: none;
+					cursor: pointer;
+				}
+				&.own:hover:not(.system) .delete-message {
+					display: inline-block;
+				}
+				.user {
+					display: inline-block;
+					font-weight: 600;
+					color: #444444;
+					margin-right: 5px;
+					&:hover {
+						color: #333;
+					}
+				}
+				.thumb {
+					position: absolute;
+					left: 0;
+					top: 0;
+					display: block;
+					width: 40px;
+					height: 40px;
+				}
+				.info {
+					font-size: 12px;
+					color: @info-font-color;
+				}
+				&.sequential {
+					margin-top: 5px;
+					min-height: 20px;
+					.user {
+						display: none;
+					}
+					.thumb {
+						display: none;
+					}
+					.info {
+						position: absolute;
+						text-align: right;
+						left: -20px;
+						width: 65px;
+						.time {
+							display: none;
+						}
+						.edited {
+							display: inline-block;
+						}
+						.edit-message {
+							float: left;
+							margin-left: 1px;
+						}
+						.delete-message {
+							float: left;
+						}
+					}
+					&:hover {
+						.time {
+							display: inline-block;
+						}
+						.edited {
+							display: none;
+						}
+					}
+				}
+				&.system {
+					.body {
+						color: @info-font-color;
+						font-style: italic;
+						text-transform: lowercase;
+						em {
+							font-weight: 600;
+						}
+					}
+				}
+				.avatar-initials {
+					line-height: 40px;
+				}
+				a {
+					color: @link-font-color;
+					font-weight: 400;
+					&:hover {
+						// color: darken(@link-font-color, 10%);
+						text-decoration: underline;
+					}
+				}
+				.body {
+					opacity: 1;
+					// .transition(opacity 1s linear);
+				}
+				&.temp .body {
+					opacity: .5;
+				}
+			}
+		}
 	}
 	.footer {
-		background-color: red;
+		background-color: #FCFCFC;
 		position: fixed;
 		bottom: 0;
 		width: 100%;
 		height: 60px;
+		border-top: 1px solid #E7E7E7;
+		// padding-right: 2em;
+		// padding: 10px;
+
+		.input-wrapper {
+			padding: 10px;
+			textarea {
+				display: block;
+				padding: 2px 8px;
+				padding-top: 9px;
+				padding-bottom: 9px;
+				padding-right: 38px;
+				overflow-y: hidden;
+				resize: none;
+				border: 1px solid #E7E7E7;
+				// margin: 10px;
+				border-radius: 5px;
+				width: 100%;
+
+				-webkit-appearance: none;
+				height: 35px;
+				line-height: normal;
+				background-color: #fff;
+				position: relative;
+				outline: none;
+			}
+		}
 	}
 }
diff --git a/packages/rocketchat-external/app/client/views/room.html b/packages/rocketchat-external/app/client/views/room.html
index d99e2e9f1ab..cfba620035a 100644
--- a/packages/rocketchat-external/app/client/views/room.html
+++ b/packages/rocketchat-external/app/client/views/room.html
@@ -3,15 +3,19 @@
 		<div class="title">
 			<h1>sala</h1>
 		</div>
-		<div class="wrapper">
-			<ul>
-				{{#each messages}}
-					{{#nrr nrrargs 'message' .}}{{/nrr}}
-				{{/each}}
-			</ul>
+		<div class="messages">
+			<div class="wrapper">
+				<ul>
+					{{#each messages}}
+						{{#nrr nrrargs 'message' .}}{{/nrr}}
+					{{/each}}
+				</ul>
+			</div>
 		</div>
 		<div class="footer">
-			<textarea class="input-message"></textarea>
+			<div class="input-wrapper">
+				<textarea class="input-message"></textarea>
+			</div>
 		</div>
 	</div>
 </template>
diff --git a/packages/rocketchat-external/app/run.sh b/packages/rocketchat-external/app/run.sh
index 996b9e26c28..e05687e2cc1 100755
--- a/packages/rocketchat-external/app/run.sh
+++ b/packages/rocketchat-external/app/run.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
 
-DDP_DEFAULT_CONNECTION_URL=http://localhost:3000
-MONGO_URL=mongodb://localhost:3001
+export DDP_DEFAULT_CONNECTION_URL=http://localhost:3000
+export MONGO_URL=mongodb://localhost:3001
 meteor -p 5000
diff --git a/packages/rocketchat-external/guests.coffee b/packages/rocketchat-external/guests.coffee
new file mode 100644
index 00000000000..11acc920349
--- /dev/null
+++ b/packages/rocketchat-external/guests.coffee
@@ -0,0 +1,3 @@
+console.log 'desativa guest ->',AccountsGuest
+AccountsGuest.forced = false
+console.log 'desativado guest ->',@AccountsGuest
diff --git a/packages/rocketchat-external/methods.coffee b/packages/rocketchat-external/methods.coffee
index f77e9603037..70e6226dc16 100644
--- a/packages/rocketchat-external/methods.coffee
+++ b/packages/rocketchat-external/methods.coffee
@@ -1,55 +1,73 @@
-@Visitor = new Meteor.Collection 'rocketchat_visitor'
+# @Visitor = new Meteor.Collection 'rocketchat_visitor'
+console.log 'registering sendMessageExternal'
 Meteor.methods
-	sendMessageExternal: (data) ->
+	sendMessageExternal: (message) ->
 		console.log 'sendMessageExternal ->',arguments
 
+		check message.rid, String
+		check message.token, String
+
 		# validate visitor and room
-		visitor = Visitor.findOne token: data.token
+		# visitor = Visitor.findOne token: message.token
+
+		# if not visitor?
+		# 	visitor =
+		# 		token: message.token
+		# 		name: 'guest'
+		# 		room: message.rid
 
-		if not visitor?
-			visitor =
-				token: data.token
-				name: 'guest'
-				room: data.rid
+		# 	visitor._id = Visitor.insert visitor
 
-			visitor._id = Visitor.insert visitor
+		# console.log visitor.room,'isnt', message.rid
 
-		console.log visitor.room,'isnt', data.rid
+		# if visitor.room isnt message.rid
+		# 	throw new Meteor.Error 'invalid-visitor-room', 'Invalid visitor room'
 
-		if visitor.room isnt data.rid
-			throw new Meteor.Error 'invalid-visitor-room', 'Invalid visitor room'
+		user = Meteor.users.findOne Meteor.userId(), fields: username: 1
+		console.log 'visitor ->',user
 
-		room = ChatRoom.findOne data.rid
+		room = ChatRoom.findOne message.rid
 
 		if not room?
 
 			# find an online user
-			user = Meteor.users.findOne { status: 'online' }
+			operator = Meteor.users.findOne { status: 'online' }
 
 			ChatRoom.insert
-				_id: data.rid
-				name: 'guest '+data.rid
+				_id: message.rid
+				name: 'guest '+message.rid
 				msgs: 1
 				lm: new Date()
-				usernames: [ user.username ]
-				t: 'c'
+				usernames: [ operator.username, user.username ]
+				t: 'p'
 				ts: new Date()
 				v:
-					token: data.token
+					token: message.token
 
 			ChatSubscription.insert
-				rid: data.rid
-				name: 'guest '+data.rid
+				rid: message.rid
+				name: 'guest '+message.rid
 				alert: true
 				open: true
 				unread: 1
 				u:
-					_id: user._id
-					username: user.username
-				t: 'c'
-
-		ChatMessage.insert
-			_id: data._id
-			ts: new Date()
-			rid: data.rid
-			msg: data.msg
+					_id: operator._id
+					username: operator.username
+				t: 'p'
+
+		room = Meteor.call 'canAccessRoom', message.rid, user._id
+
+		if not room
+			# console.log 'cannot Access Room'
+			throw new Meteor.Error 'cannot-acess-room'
+			# return false
+
+		RocketChat.sendMessage user, message, room
+
+		# Meteor.call 'sendMessage', message
+
+		# ChatMessage.insert
+		# 	_id: message._id
+		# 	ts: new Date()
+		# 	rid: message.rid
+		# 	msg: message.msg
diff --git a/packages/rocketchat-external/package.js b/packages/rocketchat-external/package.js
index 4846339699b..f6f0eb2bb74 100755
--- a/packages/rocketchat-external/package.js
+++ b/packages/rocketchat-external/package.js
@@ -18,10 +18,9 @@ Package.registerBuildPlugin({
 Package.onUse(function(api) {
 	api.versionsFrom('1.0');
 
-	api.use('coffeescript', 'server');
-	api.use('webapp', 'server');
-	api.use('autoupdate', 'server');
+	api.use(['coffeescript', 'webapp', 'autoupdate', 'artwells:accounts-guest'], 'server');
 
+	api.addFiles('guests.coffee', ['client','server']);
 	api.addFiles('external.coffee', 'server');
 	api.addFiles('methods.coffee', 'server');
 	api.addFiles('publications.coffee', 'server');
diff --git a/server/lib/accounts.coffee b/server/lib/accounts.coffee
index f91ec6d30d8..d9919d413df 100644
--- a/server/lib/accounts.coffee
+++ b/server/lib/accounts.coffee
@@ -61,6 +61,13 @@ Accounts.onCreateUser (options, user) ->
 
 Accounts.validateLoginAttempt (login) ->
 	login = RocketChat.callbacks.run 'beforeValidateLogin', login
+
+	# console.log JSON.stringify login, null, '  '
+
+	if login.user?.profile?.guest is true
+		throw new Meteor.Error 'guest-login-disabled'
+		return false
+
 	if login.allowed isnt true
 		return login.allowed
 
-- 
GitLab