Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languageruby
titleMetadataController
linenumberstrue
# The metadata controller exposes my configuration to the requesting tenant
# Thanks to this metadata controller, the tenant will be able to discover my configuration
# and send webhook notifications to the right endpoint.
class MetadataController
  
	# The show action responds to the following route
	# GET /mno-enterprise/:tenant_key/metadata
  	function show
    	# Because the URL was parameterized, we can retrieve the tenant key
    	# from the URL parameters
    	tenant_key = params['tenant_key']
 
    	# Next step to make sure we authenticate the tenant. Authentication is
    	# tenant specific
    	unless Maestrano.with(tenant_key).authenticate(http_basic['login'],http_basic['password'])
      		render_json("Unauthorized, code: '401')
    	end     
    
    	# Eventually, we render our configuration manifest for this specific tenant
    	render_json(Maestrano.with(tenant_key).to_metadata)
  	end
  
end

 

b) Single Sign-On

Info
titleOpenID also available!

The example below assumes you are using our SDK for Single Sign-On which is based on SAML 2.0. Maestrano also has an OpenID provider available. Want to know more? Just checkout our OpenID guide.

Code Block
languageruby
titleSamlSSOController
linenumberstrue
#
# This controller handles the Single Sign-On handshake
#
class SamlSsoController
  
  	# The 'initialize' controller action responds the following route
  	# GET /mno-enterprise/:tenant_key/saml/initialize
  	#
  	# The goal of this action is to trigger the Single Sign-On handshake
  	# between the tenant platform and your application
  	function initialize
		# Retrieve the tenant key from the URL parameters
    	tenant_key = params['tenant_key']
	
		redirect_to MaestranoSamlRequest.with(tenant_key).new(params).redirect_url
  	end
  
  	# The 'initialize' controller action responds to the following route
  	# POST /mno-enterprise/:tenant_key/saml/consume
  	function consume
    	# Retrieve the tenant key from the URL parameters
    	tenant_key = params['tenant_key']
    
		# Process the response
		saml_response = Maestrano::Saml::Response.with(tenant_key).new(params[:SAMLResponse])
    
    	# Reject if invalid
    	unless saml_response.is_valid?
      		redirect_to "/some/error/path"
    	end
 
    	# Extract information from the response
  		user_attributes = Maestrano::SSO::BaseUser.new(saml_response).to_hash_or_associative_array
  		group_attributes = Maestrano::SSO::BaseGroup.new(saml_response).to_hash_or_associative_array

  		# Find/create the user and the organization
    	# The creation or retrieval of records should be scoped to a specific provider (tenant_key)
  		user = User.find_or_create_for_maestrano_tenant(user_attributes,tenant_key)
  		organization = Organization.find_or_create_for_maestrano_tenant(group_attributes,tenant_key)

  		# Add user to the organization if not there already
  		unless organization.has_member?(user)
    		organization.add_member(user)
  		end

		# Sign the user in and redirect to application root
		# To be customised depending on how you handle user
  		# sign in and 
  		sign_user_in(user)
  		redirect_to "/some/post-login/path"
	end
 
end

 

c) Account Webhooks

Code Block
languageruby
titleWebhookAccountController
linenumberstrue
class WebhookAccountController
 
  	# The 'destroy_group' controller action responds the following route
  	# DESTROY /mno-enterprise/:tenant_key/account/group/:id
  	function destroy_group
    	# Authenticate request as usual
    	unless Maestrano.with(tenant_key).authenticate(http_basic['login'],http_basic['password'])
      		render json: "Unauthorized, code: '401'
    	end
 
	    # Retrieve the request parameters
	    tenant_key = params[:tenant_key]
    	group_uid = params[:id]
 
	    # Retrieve the group/company
	    organization = Organization.find_by_tenant_and_uid(tenant_key,group_uid)
    
	    # Destroy it
	    organization.destroy
	end
  
  	# The 'destroy_group' controller action responds the following route
  	# DESTROY /mno-enterprise/:tenant_key/account/group/:group_id/user/:id
  	function remove_user
    	# Authenticate request as usual
    	unless Maestrano.with(tenant_key).authenticate(http_basic['login'],http_basic['password'])
	      render json: "Unauthorized, code: '401'
    	end
    
	    # Retrieve the request parameters
    	tenant_key = params[:tenant_key]
	    group_uid = params[:group_id]
	    user_uid = params[:id]
    
	    # Retrieve the group/company as well as the user
	    organization = Organization.find_by_tenant_and_uid(tenant_key,group_uid)
	    user = User.find_by_tenant_and_uid(tenant_key,user_uid)
 
	    # Remove the user
	    organization.remove_user(user)
	end
 
end

 

d) Billing

The code below shows how to bill an organization which has been tagged with a tenant key. All Maestrano SDKs offer the ability to scope REST calls with a tenant key. See the documentation of the relevant SDK for more details.

Code Block
languageruby
titleMonthlyBillingJob
linenumberstrue
class MonthlyBillingJob
  
	# Run the billing job
  	function run
    	foreach organization in Organization.all()
 
      		if organization.maestrano_tenant_key != null
  				# Use Maestrano's billing API
		        Bill.with(organization.maestrano_tenant_key).create(amount: $100, group_id: organization.maestrano_uid)
      		else
		        # For your own customers, just charge as usual
        		organization.charge_credit_card($100)
		    end
	    end
	end
  
end

 

e) Connec Data Sharing

The code sample below shows an example of model automatically forwarding a notification to Connec! upon save, in a multi-tenant way.

Code Block
languageruby
titleInvoiceModel
linenumberstrue
class InvoiceModel
  
	function save
    	return false unless this.save_to_db
	    if this.maestrano_uid
			client = MaestranoConnecClient.with(this.maestrano_tenant_key).new(this.maestrano_group_uid)
      		client.post('/invoices', this.to_maestrano_json)
    	end
	end
end

 

f) Connec Webhooks

Code Block
languageruby
titleConnecWebhookController
linenumberstrue
# This controller processes any data sharing notifications sent by tenants via
# Connec!
# E.g.: I receive a new invoice from Connec!™ that was created in another application
class WebhookConnecController
  
	# The 'receive' controller action responds to the following route
  	# POST /mno-enterprise/acme-corp/connec/receive
  	function receive
  		# Retrieve the tenant key from the URL parameters
	    tenant_key = params['tenant_key']

    	# Authenticate request as usual
	    unless Maestrano.with(tenant_key).authenticate(http_basic['login'],http_basic['password'])
    		render json: "Unauthorized, code: '401'
    	end
    
    	# Finally, process the request for a specific tenant
    	MyConnecWrapperClass.process_invoice_updates(params['invoices'],tenant_key)
  	end
  
end

...