[hub] merge with upstream
diff --git a/erpnext/hub_node/api.py b/erpnext/hub_node/api.py
index fe41919..af34844 100644
--- a/erpnext/hub_node/api.py
+++ b/erpnext/hub_node/api.py
@@ -1,11 +1,62 @@
 from __future__ import unicode_literals
-import frappe, json
-import io, base64, os, requests
+
+import frappe
+import json
+import io
+import base64
+import os
+import requests
+
+from frappe import _
 from frappe.frappeclient import FrappeClient
 from frappe.desk.form.load import get_attachments
 from frappe.utils.file_manager import get_file_path
 from six import string_types
 
+current_user = frappe.session.user
+
+
+@frappe.whitelist()
+def register_marketplace(**kwargs):
+	settings = frappe.get_single('Marketplace Settings')
+	settings.update(kwargs)
+	settings.users = []
+
+	validate_registerer()
+	message = settings.register()
+
+	if message.get('email'):
+		settings.registered = 1
+
+		settings.append('users', {
+			'user': current_user,
+			'name': current_user,
+			'username': kwargs.get('username'),
+			'password': message.get('password')
+		})
+
+		user_emails = kwargs.get('users').strip()[:-1].split(', ')
+		for email in user_emails:
+			settings.append('users', {'user': email, 'name': email})
+
+		settings.insert()
+
+	return message
+
+
+@frappe.whitelist()
+def register_user(username, first_name, company):
+	pass
+
+
+def validate_registerer():
+	if current_user == 'Administrator':
+		frappe.throw(_('Please login as another user to register on Marketplace'))
+
+	if 'System Manager' not in frappe.get_roles():
+		frappe.throw(_('Only users with System Manager role can register on Marketplace'), frappe.PermissionError)
+
+
 @frappe.whitelist()
 def call_hub_method(method, params=None):
 	connection = get_hub_connection()
@@ -20,6 +71,7 @@
 	response = connection.post_request(params)
 	return response
 
+
 def map_fields(items):
 	field_mappings = get_field_mappings()
 	table_fields = [d.fieldname for d in frappe.get_meta('Item').get_table_fields()]
@@ -44,6 +96,7 @@
 
 	return items
 
+
 @frappe.whitelist()
 def get_valid_items(search_value=''):
 	items = frappe.get_list(
@@ -68,6 +121,7 @@
 
 	return valid_items
 
+
 @frappe.whitelist()
 def publish_selected_items(items_to_publish):
 	items_to_publish = json.loads(items_to_publish)
@@ -85,7 +139,6 @@
 			'image_list': item.get('image_list')
 		}).insert(ignore_if_duplicate=True)
 
-
 	items = map_fields(items_to_publish)
 
 	try:
@@ -100,6 +153,7 @@
 	except Exception as e:
 		frappe.log_error(message=e, title='Hub Sync Error')
 
+
 def item_sync_preprocess(intended_item_publish_count):
 	response = call_hub_method('pre_items_publish', {
 		'intended_item_publish_count': intended_item_publish_count
@@ -111,6 +165,7 @@
 	else:
 		frappe.throw('Unable to update remote activity')
 
+
 def item_sync_postprocess():
 	response = call_hub_method('post_items_publish', {})
 	if response:
@@ -147,24 +202,22 @@
 
 
 def get_hub_connection():
-	read_only = True
+	settings = frappe.get_single('Marketplace Settings')
+	marketplace_url = settings.marketplace_url
+	current_user_records = filter(
+		lambda x: x.user == current_user and x.password,
+		settings.users
+	)
 
-	if frappe.db.exists('Data Migration Connector', 'Hub Connector'):
-		hub_connector = frappe.get_doc('Data Migration Connector', 'Hub Connector')
-
-		# full rights to user who registered as hub_seller
-		if hub_connector.username == frappe.session.user:
-			read_only = False
-
-		if not read_only:
-			hub_connection = hub_connector.get_connection()
-			return hub_connection.connection
-
-	# read-only connection
-	if read_only:
-		hub_url = frappe.db.get_single_value('Marketplace Settings', 'hub_url')
-		hub_connection = FrappeClient(hub_url)
+	if current_user_records:
+		record = current_user_records[0]
+		password = frappe.get_doc('Hub User', current_user).get_password()
+		hub_connection = FrappeClient(marketplace_url, record.user, password)
 		return hub_connection
+	else:
+		read_only_hub_connection = FrappeClient(marketplace_url)
+		return read_only_hub_connection
+
 
 def get_field_mappings():
 	return []
diff --git a/erpnext/hub_node/doctype/hub_user/__init__.py b/erpnext/hub_node/doctype/hub_user/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hub_node/doctype/hub_user/__init__.py
diff --git a/erpnext/hub_node/doctype/hub_user/hub_user.json b/erpnext/hub_node/doctype/hub_user/hub_user.json
new file mode 100644
index 0000000..08a59c6
--- /dev/null
+++ b/erpnext/hub_node/doctype/hub_user/hub_user.json
@@ -0,0 +1,140 @@
+{
+ "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "autoname": "field:user", 
+ "beta": 0, 
+ "creation": "2018-08-31 12:36:45.627531", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "user", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "User", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "User", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 1
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "username", 
+   "fieldtype": "Data", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Hub Username", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "password", 
+   "fieldtype": "Password", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
+   "in_list_view": 1, 
+   "in_standard_filter": 0, 
+   "label": "Hub Password", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 1, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 0, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "translatable": 0, 
+   "unique": 0
+  }
+ ], 
+ "has_web_view": 0, 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2018-09-01 09:46:54.327880", 
+ "modified_by": "cave@aperture.com", 
+ "module": "Hub Node", 
+ "name": "Hub User", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "show_name_in_global_search": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/hub_node/doctype/hub_user/hub_user.py b/erpnext/hub_node/doctype/hub_user/hub_user.py
new file mode 100644
index 0000000..de43f4e
--- /dev/null
+++ b/erpnext/hub_node/doctype/hub_user/hub_user.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class HubUser(Document):
+	pass
diff --git a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.json b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.json
index 5243f38..066202a 100644
--- a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.json
+++ b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.json
@@ -215,8 +215,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "company_email", 
-   "fieldtype": "Data", 
+   "fieldname": "company_logo", 
+   "fieldtype": "Attach Image", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -224,7 +224,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Company Email", 
+   "label": "Company Logo", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -344,8 +344,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "logo", 
-   "fieldtype": "Attach Image", 
+   "fieldname": "company_description", 
+   "fieldtype": "Long Text", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -353,7 +353,7 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Company Logo", 
+   "label": "Company Description", 
    "length": 0, 
    "no_copy": 0, 
    "permlevel": 0, 
@@ -376,8 +376,8 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "company_description", 
-   "fieldtype": "Text Editor", 
+   "fieldname": "users", 
+   "fieldtype": "Table", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -385,9 +385,10 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Description", 
+   "label": "Users", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Hub User", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -479,8 +480,8 @@
  "issingle": 1, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-08-31 17:30:37.305704", 
- "modified_by": "netchamp@rawcoderz.com", 
+ "modified": "2018-08-31 22:14:59.497780", 
+ "modified_by": "cave@aperture.com", 
  "module": "Hub Node", 
  "name": "Marketplace Settings", 
  "name_case": "", 
diff --git a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py
index 9b83898..f0046d0 100644
--- a/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py
+++ b/erpnext/hub_node/doctype/marketplace_settings/marketplace_settings.py
@@ -15,90 +15,29 @@
 	def validate(self):
 		self.site_name = frappe.utils.get_url()
 
+
 	def get_marketplace_url(self):
 		return self.marketplace_url
 
+
 	def register(self):
 		""" Create a User on hub.erpnext.org and return username/password """
-
-		if frappe.session.user == 'Administrator':
-			frappe.throw(_('Please login as another user to register on Marketplace'))
-
-		if 'System Manager' not in frappe.get_roles():
-			frappe.throw(_('Only users with System Manager role can register on Marketplace'), frappe.PermissionError)
-
 		self.site_name = frappe.utils.get_url()
 
-		data = {
-			'profile': self.as_json()
-		}
-		post_url = self.get_marketplace_url() + '/api/method/hub.hub.api.register'
+		register_url = self.get_marketplace_url() + '/api/method/hub.hub.api.register'
+		data = {'profile': self.as_json(), 'email': frappe.session.user}
+		headers = {'accept': 'application/json'}
 
-		response = requests.post(post_url, data=data, headers = {'accept': 'application/json'})
-
+		response = requests.post(register_url, data = data, headers = headers)
 		response.raise_for_status()
-
 		if response.ok:
 			message = response.json().get('message')
 		else:
 			frappe.throw(json.loads(response.text))
 
-		if message.get('email'):
-			self.create_hub_connector(message)
-			self.registered = 1
-			self.save()
-
 		return message or None
 
-	# def unregister(self):
-	# 	""" Disable the User on hub.erpnext.org"""
 
-	# 	hub_connector = frappe.get_doc(
-	# 		'Data Migration Connector', 'Hub Connector')
-
-	# 	connection = hub_connector.get_connection()
-	# 	response_doc = connection.update('User', frappe._dict({'enabled': 0}), hub_connector.username)
-
-	# 	if response_doc['enabled'] == 0:
-	# 		self.enabled = 0
-	# 		self.save()
-
-	def create_hub_connector(self, message):
-		if frappe.db.exists('Data Migration Connector', 'Hub Connector'):
-			hub_connector = frappe.get_doc('Data Migration Connector', 'Hub Connector')
-			hub_connector.hostname = self.get_marketplace_url()
-			hub_connector.username = message['email']
-			hub_connector.password = message['password']
-			hub_connector.save()
-			return
-
-		frappe.get_doc({
-			'doctype': 'Data Migration Connector',
-			'connector_type': 'Frappe',
-			'connector_name': 'Hub Connector',
-			'hostname': self.get_marketplace_url(),
-			'username': message['email'],
-			'password': message['password']
-		}).insert()
-
-def reset_hub_publishing_settings(last_sync_datetime = ""):
-	doc = frappe.get_doc("Marketplace Settings", "Marketplace Settings")
-	doc.reset_publishing_settings(last_sync_datetime)
-	doc.in_callback = 1
-	doc.save()
-
-def reset_hub_settings(last_sync_datetime = ""):
-	doc = frappe.get_doc("Marketplace Settings", "Marketplace Settings")
-	doc.reset_publishing_settings(last_sync_datetime)
-	doc.reset_enable()
-	doc.in_callback = 1
-	doc.save()
-	frappe.msgprint(_("Successfully unregistered."))
-
-@frappe.whitelist()
-def register_seller(**kwargs):
-	settings = frappe.get_doc('Marketplace Settings')
-	settings.update(kwargs)
-	message = settings.register()
-
-	return message.get('email')
+	def unregister(self):
+		""" Disable the User on hub.erpnext.org"""
+		pass
diff --git a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js
new file mode 100644
index 0000000..fba3e09
--- /dev/null
+++ b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Marketplace Settings", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially([
+		// insert a new Marketplace Settings
+		() => frappe.tests.make('Marketplace Settings', [
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py
new file mode 100644
index 0000000..549b991
--- /dev/null
+++ b/erpnext/hub_node/doctype/marketplace_settings/test_marketplace_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+
+class TestMarketplaceSettings(unittest.TestCase):
+	pass
diff --git a/erpnext/public/js/hub/Sidebar.vue b/erpnext/public/js/hub/Sidebar.vue
index cff580e..6e0b26c 100644
--- a/erpnext/public/js/hub/Sidebar.vue
+++ b/erpnext/public/js/hub/Sidebar.vue
@@ -19,7 +19,7 @@
 export default {
 	data() {
 		return {
-			hub_registered: hub.settings.registered && frappe.session.user === hub.settings.company_email,
+			hub_registered: hub.settings.registered,
 			items: [
 				{
 					label: __('Browse'),
diff --git a/erpnext/public/js/hub/components/profile_dialog.js b/erpnext/public/js/hub/components/profile_dialog.js
index ae44659..03e7f48 100644
--- a/erpnext/public/js/hub/components/profile_dialog.js
+++ b/erpnext/public/js/hub/components/profile_dialog.js
@@ -1,6 +1,12 @@
 const ProfileDialog = (title = __('Edit Profile'), action={}) => {
 	const fields = [
 		{
+			// TODO: add hub check for taken
+			fieldname: 'username',
+			label: __('Username'),
+			fieldtype: 'Data'
+		},
+		{
 			fieldtype: 'Link',
 			fieldname: 'company',
 			label: __('Company'),
@@ -25,6 +31,11 @@
 			fieldtype: 'Read Only'
 		},
 		{
+			fieldname: 'users',
+			label: __('Users'),
+			fieldtype: 'MultiSelect'
+		},
+		{
 			fieldname: 'country',
 			label: __('Country'),
 			fieldtype: 'Read Only'
@@ -62,6 +73,13 @@
 		}
 	});
 
+	frappe.db.get_list('User')
+		.then(result => {
+			const users = result.map(result => result.name)
+				.filter(user => !['Guest', 'Administrator', frappe.session.user].includes(user));
+			dialog.fields_dict.users.set_data(users);
+		});
+
 	// Post create
 	const default_company = frappe.defaults.get_default('company');
 	dialog.set_value('company', default_company);
diff --git a/erpnext/public/js/hub/marketplace.js b/erpnext/public/js/hub/marketplace.js
index 7659a36..bea30bd 100644
--- a/erpnext/public/js/hub/marketplace.js
+++ b/erpnext/public/js/hub/marketplace.js
@@ -92,16 +92,16 @@
 			__('Become a Seller'),
 			{
 				label: __('Register'),
-				on_submit: this.register_seller.bind(this)
+				on_submit: this.register_marketplace.bind(this)
 			}
 		);
 
 		this.register_dialog.show();
 	}
 
-	register_seller(form_values) {
+	register_marketplace(form_values) {
 		frappe.call({
-		    method: 'erpnext.hub_node.doctype.marketplace_settings.marketplace_settings.register_seller',
+		    method: 'erpnext.hub_node.api.register_marketplace',
 		    args: form_values
 		}).then(() => {
 			this.register_dialog.hide();