class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer( help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer( help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' dbname_template = fields.Char( 'DB Names', help= 'Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.odoo.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.one def _new_database_vals(self, vals): vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None): self.ensure_one() server = self.server_id if not server: server = self.env['saas_portal.server'].get_saas_server() server.action_sync_server() if not partner_id and user_id: user = self.env['res.users'].browse(user_id) partner_id = user.partner_id.id if not trial and self.maximum_allowed_dbs_per_partner != 0: db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', False) ]) if db_count >= self.maximum_allowed_dbs_per_partner: raise MaximumDBException( "Limit of databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_dbs_per_partner}) if trial and self.maximum_allowed_trial_dbs_per_partner != 0: trial_db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', True) ]) if trial_db_count >= self.maximum_allowed_trial_dbs_per_partner: raise MaximumTrialDBException( "Limit of trial databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_trial_dbs_per_partner}) vals = { 'name': dbname or self.generate_dbname()[0], 'server_id': server.id, 'plan_id': self.id, 'partner_id': partner_id, 'trial': trial, 'support_team_id': support_team_id, } client = None if client_id: vals['client_id'] = client_id client = self.env['saas_portal.client'].search([('client_id', '=', client_id)]) vals = self._new_database_vals(vals)[0] if client: client.write(vals) else: client = self.env['saas_portal.client'].create(vals) client_id = client.client_id scheme = server.request_scheme port = server.request_port if user_id: owner_user = self.env['res.users'].browse(user_id) else: owner_user = self.env.user owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'name': owner_user.name, 'email': owner_user.email, } trial_expiration_datetime = ( datetime.strptime(client.create_date, DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(hours=self.expiration)).strftime( DEFAULT_SERVER_DATETIME_FORMAT) # for trial state = { 'd': client.name, 'e': trial and trial_expiration_datetime or client.create_date, 'r': '%s://%s:%s/web' % (scheme, client.name, port), 'owner_user': owner_user_data, 't': client.trial, } if self.template_id: state.update({'db_template': self.template_id.name}) scope = ['userinfo', 'force_login', 'trial', 'skiptheuse'] url = server._request_server( path='/saas_server/new_database', scheme=scheme, port=port, state=state, client_id=client_id, scope=scope, )[0] res = requests.get(url, verify=(self.server_id.request_scheme == 'https' and self.server_id.verify_ssl)) if res.status_code != 200: # TODO /saas_server/new_database show more details here raise exceptions.Warning('Error %s' % res.status_code) data = simplejson.loads(res.text) params = { 'state': data.get('state'), 'access_token': client.oauth_application_id._get_access_token(user_id, create=True), } url = '{url}?{params}'.format(url=data.get('url'), params=werkzeug.url_encode(params)) # send email if notify_user: template = self.env.ref('saas_portal.email_template_create_saas') client.message_post_with_template(template.id, composition_mode='comment') if trial: client.expiration_datetime = trial_expiration_datetime client.send_params_to_client_db() client.server_id.action_sync_server() return {'url': url, 'id': client.id, 'client_id': client_id}
class SaasPortalPlan(models.Model): _name = 'saas_portal.plan' name = fields.Char('Plan', required=True) summary = fields.Char('Summary') template_id = fields.Many2one('saas_portal.database', 'Template', ondelete='restrict') demo = fields.Boolean('Install Demo Data') maximum_allowed_dbs_per_partner = fields.Integer( help='maximum allowed non-trial databases per customer', require=True, default=0) maximum_allowed_trial_dbs_per_partner = fields.Integer( help='maximum allowed trial databases per customer', require=True, default=0) max_users = fields.Char('Initial Max users', default='0', help='leave 0 for no limit') total_storage_limit = fields.Integer('Total storage limit (MB)') block_on_expiration = fields.Boolean('Block clients on expiration', default=False) block_on_storage_exceed = fields.Boolean('Block clients on storage exceed', default=False) def _get_default_lang(self): return self.env.lang def _default_tz(self): return self.env.user.tz lang = fields.Selection(scan_languages(), 'Language', default=_get_default_lang) tz = fields.Selection(_tz_get, 'TimeZone', default=_default_tz) sequence = fields.Integer('Sequence') state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', compute='_get_state', store=True) expiration = fields.Integer('Expiration (hours)', help='time to delete database. Use for demo') _order = 'sequence' grace_period = fields.Integer('Grace period (days)', help='initial days before expiration') dbname_template = fields.Char( 'DB Names', help= 'Used for generating client database domain name. Use %i for numbering. Ignore if you use manually created db names', placeholder='crm-%i.odoo.com') server_id = fields.Many2one('saas_portal.server', string='SaaS Server', ondelete='restrict', help='User this saas server or choose random') website_description = fields.Html('Website description') logo = fields.Binary('Logo') on_create = fields.Selection([ ('login', 'Log into just created instance'), ], string="Workflow on create", default='login') on_create_email_template = fields.Many2one('email.template') @api.one @api.depends('template_id.state') def _get_state(self): if self.template_id.state == 'template': self.state = 'confirmed' else: self.state = 'draft' @api.multi def _new_database_vals(self, vals): self.ensure_one() vals['max_users'] = self.max_users vals['total_storage_limit'] = self.total_storage_limit vals['block_on_expiration'] = self.block_on_expiration vals['block_on_storage_exceed'] = self.block_on_storage_exceed return vals @api.multi def _prepare_owner_user_data(self, user_id): """ Prepare the dict of values to update owner user data in client instalnce. This method may be overridden to implement custom values (making sure to call super() to establish a clean extension chain). """ self.ensure_one() owner_user = self.env['res.users'].browse(user_id) or self.env.user owner_user_data = { 'user_id': owner_user.id, 'login': owner_user.login, 'name': owner_user.name, 'email': owner_user.email, 'password_crypt': owner_user.password_crypt, } return owner_user_data @api.multi def _get_expiration(self, trial): self.ensure_one() trial_hours = trial and self.expiration initial_expiration_datetime = datetime.now() trial_expiration_datetime = (initial_expiration_datetime + timedelta( hours=trial_hours)).strftime(DEFAULT_SERVER_DATETIME_FORMAT) return trial and trial_expiration_datetime or initial_expiration_datetime.strftime( DEFAULT_SERVER_DATETIME_FORMAT) @api.multi def create_new_database(self, **kwargs): return self._create_new_database(**kwargs) @api.multi def _create_new_database(self, dbname=None, client_id=None, partner_id=None, user_id=None, notify_user=False, trial=False, support_team_id=None, async=None): self.ensure_one() server = self.server_id if not server: server = self.env['saas_portal.server'].get_saas_server() # server.action_sync_server() if not partner_id and user_id: user = self.env['res.users'].browse(user_id) partner_id = user.partner_id.id if not trial and self.maximum_allowed_dbs_per_partner != 0: db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', False) ]) if db_count >= self.maximum_allowed_dbs_per_partner: raise MaximumDBException( "Limit of databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_dbs_per_partner}) if trial and self.maximum_allowed_trial_dbs_per_partner != 0: trial_db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', True) ]) if trial_db_count >= self.maximum_allowed_trial_dbs_per_partner: raise MaximumTrialDBException( "Limit of trial databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_trial_dbs_per_partner}) client_expiration = self._get_expiration(trial) vals = { 'name': dbname or self.generate_dbname(), 'server_id': server.id, 'plan_id': self.id, 'partner_id': partner_id, 'trial': trial, 'support_team_id': support_team_id, 'expiration_datetime': client_expiration, } client = None if client_id: vals['client_id'] = client_id client = self.env['saas_portal.client'].search([('client_id', '=', client_id)]) vals = self._new_database_vals(vals) if client: client.write(vals) else: client = self.env['saas_portal.client'].create(vals) client_id = client.client_id owner_user_data = self._prepare_owner_user_data(user_id) state = { 'd': client.name, 'public_url': client.public_url, 'e': client_expiration, 'r': client.public_url + 'web', 'owner_user': owner_user_data, 't': client.trial, } if self.template_id: state.update({'db_template': self.template_id.name}) scope = ['userinfo', 'force_login', 'trial', 'skiptheuse'] req, req_kwargs = server._request_server( path='/saas_server/new_database', state=state, client_id=client_id, scope=scope, ) res = requests.Session().send(req, **req_kwargs) if res.status_code != 200: raise Warning('Error on request: %s\nReason: %s \n Message: %s' % (req.url, res.reason, res.content)) data = simplejson.loads(res.text) params = { 'state': data.get('state'), 'access_token': client.oauth_application_id._get_access_token(user_id, create=True), } url = '{url}?{params}'.format(url=data.get('url'), params=werkzeug.url_encode(params)) auth_url = url # send email # TODO: get rid of such attributes as ``notify_user``, ``trial`` - move them on plan settings (use different plans for trials and non-trials) if notify_user or self.on_create == 'email': template = self.on_create_email_template if template: email_ctx = { 'default_model': 'saas_portal.client', 'default_res_id': client.id, 'default_use_template': bool(template), 'default_template_id': template.id, 'default_composition_mode': 'comment', } client.send_params_to_client_db() # TODO make async call of action_sync_server here # client.server_id.action_sync_server() client.sync_client() return { 'url': url, 'id': client.id, 'client_id': client_id, 'auth_url': auth_url }
if not server: server = self.env['saas_portal.server'].get_saas_server() #server.action_sync_server() if not partner_id and user_id: user = self.env['res.users'].browse(user_id) partner_id = user.partner_id.id if not trial and self.maximum_allowed_dbs_per_partner != 0: db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', False) ]) if db_count >= self.maximum_allowed_dbs_per_partner: raise MaximumDBException( "Limit of databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_dbs_per_partner}) if trial and self.maximum_allowed_trial_dbs_per_partner != 0: trial_db_count = self.env['saas_portal.client'].search_count([ ('partner_id', '=', partner_id), ('state', '=', 'open'), ('plan_id', '=', self.id), ('trial', '=', True) ]) if trial_db_count >= self.maximum_allowed_trial_dbs_per_partner: raise MaximumTrialDBException( "Limit of trial databases for this plan is %(maximum)s reached" % {'maximum': self.maximum_allowed_trial_dbs_per_partner}) vals = { 'name': dbname or self.generate_dbname()[0], 'server_id': server.id, 'plan_id': self.id,