Example #1
0
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
        }
Example #2
0
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}