def setup(self): # Make sure Unix user/group are active users = UsersBackend(self.app) users.add_sys_with_home('sparkleshare') users.add_group('sparkleshare') users.add_to_group('sparkleshare', 'sparkleshare') users.change_user_param('sparkleshare', 'shell', '/usr/bin/git-shell') if not os.path.exists('/home/sparkleshare'): os.makedirs('/home/sparkleshare') # Configure SSH if not os.path.exists('/home/sparkleshare/.ssh'): os.makedirs('/home/sparkleshare/.ssh') os.chmod('/home/sparkleshare/.ssh', 0700) if not os.path.exists('/home/sparkleshare/.ssh/authorized_keys'): open('/home/sparkleshare/.ssh/authorized_keys', 'w').write('') os.chmod('/home/sparkleshare/.ssh/authorized_keys', 0600) f = open('/etc/ssh/sshd_config', 'r').read() if not '# SparkleShare' in f: f += '\n' f += '# SparkleShare\n' f += '# Please do not edit the above comment as it\'s used as a check by Dazzle/Genesis\n' f += 'Match User sparkleshare\n' f += ' PasswordAuthentication no\n' f += ' PubkeyAuthentication yes\n' f += '# End of SparkleShare configuration\n' open('/etc/ssh/sshd_config', 'w').write(f) self.app.get_backend(apis.services.IServiceManager).restart('sshd')
def enable_ssl(self, cert, key): ub = UsersBackend(self.app) ub.add_to_group('umurmur', 'ssl-cert') config = UMurmurConfig(self.app) config.load() config.config.certificate = cert config.config.private_key = key config.save()
def chkpath(self): # Make sure the db dir exists and that it has the right perms users = UsersBackend(self.app) try: gid = int(users.get_group("sqlite3", users.get_all_groups()).gid) except AttributeError: users.add_group("sqlite3") users.add_to_group("http", "sqlite3") gid = int(users.get_group("sqlite3", users.get_all_groups()).gid) if not os.path.isdir('/var/lib/sqlite3'): os.makedirs('/var/lib/sqlite3') if oct(stat.S_IMODE(os.stat('/var/lib/sqlite3').st_mode)) != 0775: os.chmod('/var/lib/sqlite3', 0775) if int(os.stat('/var/lib/sqlite3').st_gid) != gid: os.chown('/var/lib/sqlite3', -1, gid) del users
def post_install(self, name, path, vars, dbinfo={}): users = UsersBackend(self.app) users.add_user('gollum') s = self.app.get_backend(apis.services.IServiceManager) s.edit('gollum', { 'stype': 'program', 'directory': path, 'user': '******', 'command': 'gollum', 'autostart': 'true', 'autorestart': 'true', 'stdout_logfile': '/var/log/gollum.log', 'stderr_logfile': '/var/log/gollum.log' } ) s.enable('gollum', 'supervisor') shell("chown gollum %s" % path) shell("GIT_DIR=%s git init" % os.path.join(path, ".git"))
def post_install(self, name, path, vars, dbinfo={}): nodectl = apis.langassist(self.app).get_interface('NodeJS') users = UsersBackend(self.app) d = json.loads(open(os.path.join(path, 'config.js'), 'r').read()) if d["storage"]["type"] == "redis": d["storage"]["type"] = "file" d["storage"]["path"] = "./data" if d["storage"].has_key("host"): del d["storage"]["host"] if d["storage"].has_key("port"): del d["storage"]["port"] if d["storage"].has_key("db"): del d["storage"]["db"] if d["storage"].has_key("expire"): del d["storage"]["expire"] open(os.path.join(path, 'config.js'), 'w').write(json.dumps(d)) nodectl.install_from_package(path) users.add_user('haste') s = self.app.get_backend(apis.services.IServiceManager) s.edit('haste', { 'stype': 'program', 'directory': path, 'user': '******', 'command': 'node %s'%os.path.join(path, 'server.js'), 'autostart': 'true', 'autorestart': 'true', 'environment': 'NODE_ENV="production"', 'stdout_logfile': '/var/log/haste.log', 'stderr_logfile': '/var/log/haste.log' } ) s.enable('haste', 'supervisor') # Finally, make sure that permissions are set so that Haste # can save its files properly. shell('chown -R haste ' + path)
def __init__(self): self.configDir = '/home/syncthing/.config/syncthing' self.configFile = os.path.join(self.configDir, 'config.xml') if not os.path.exists(self.configFile): if not os.path.exists(self.configDir): UsersBackend(self.app).add_sys_with_home('syncthing') os.makedirs(self.configDir) uid = pwd.getpwnam('syncthing').pw_uid for r, d, f in os.walk('/home/syncthing'): for x in d: os.chown(os.path.join(r, x), uid, -1) for x in f: os.chown(os.path.join(r, x), uid, -1) self.app.get_backend(apis.services.IServiceManager).real_restart('syncthing@syncthing')
def initial_setup(self): # Grab frameworks for use later config = MailConfig(self.app) users = UsersBackend(self.app) dbase = apis.databases(self.app).get_interface('SQLite3') config.load() # Create a SQLite3 database for storing mailbox, alias and # domain information if 'vmail' in [x['name'] for x in dbase.get_dbs()]: dbase.remove('vmail') dbase.add('vmail') sql = ('CREATE TABLE "alias" (' 'address varchar(255) NOT NULL default "", ' 'goto text NOT NULL, domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (address)); ' 'CREATE TABLE "domain" ( ' 'domain varchar(255) NOT NULL default "", ' 'transport varchar(255) default NULL, ' 'backupmx tinyint(1) NOT NULL default "0", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (domain)); ' 'CREATE TABLE "alias_domain" ( ' 'alias_domain varchar(255) NOT NULL default "", ' 'target_domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (alias_domain)); ' 'CREATE TABLE "mailbox" ( ' 'username varchar(255) NOT NULL default "", ' 'password varchar(255) NOT NULL default "", ' 'name varchar(255) NOT NULL default "", ' 'maildir varchar(255) NOT NULL default "", ' 'quota bigint(20) NOT NULL default "0", ' 'local_part varchar(255) NOT NULL default "", ' 'domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (username));' 'CREATE INDEX address ON alias (address);' 'CREATE INDEX active ON alias_domain (active);' 'CREATE INDEX target_domain ON alias_domain (target_domain);' 'CREATE INDEX username ON mailbox (username);') dbase.execute('vmail', sql) # Add system user and group for handling mail users.add_sys_user('vmail') users.add_group('vmail') users.add_to_group('vmail', 'vmail') uid = int(users.get_user('vmail', users.get_all_users()).uid) gid = int(users.get_group('vmail', users.get_all_groups()).gid) pfgid = int(users.get_group('dovecot', users.get_all_groups()).gid) # Create the virtual mail directory if not os.path.exists('/var/vmail'): os.mkdir('/var/vmail') users.change_user_param('vmail', 'home', '/var/vmail') users.change_user_param('vmail', 'shell', '/sbin/nologin') os.chmod('/var/vmail', 0770) os.chown('/var/vmail', uid, gid) # Tell Dovecot (MDA) where to find users and passwords config.dovecot_authsql = { 'passdb_0': { 'driver': 'sql', 'args': '/etc/dovecot/dovecot-sql.conf.ext' }, 'userdb_0': { 'driver': 'sql', 'args': '/etc/dovecot/dovecot-sql.conf.ext' } } # Tell Dovecot how to read our SQL config.dovecot_dovecotsql['driver'] = 'sqlite' config.dovecot_dovecotsql['connect'] = '/var/lib/sqlite3/vmail.db' config.dovecot_dovecotsql['default_pass_scheme'] = 'MD5-CRYPT' config.dovecot_dovecotsql['password_query'] = ( 'SELECT username as user, password, \'/var/vmail/%d/%n\'' ' as userdb_home, \'maildir:/var/vmail/%d/%n\' as userdb_mail,' ' ' + str(uid) + ' as userdb_uid, ' + str(gid) + ' as userdb_gid FROM mailbox ' 'WHERE username = \'%u\' AND active = \'1\'') config.dovecot_dovecotsql['user_query'] = ( 'SELECT \'/var/vmail/%d/%n\' as home, ' '\'maildir:/var/vmail/%d/%n\' as mail, ' + str(uid) + ' AS uid, ' + str(gid) + ' AS gid, ' '\'dirsize:storage=\'|| quota AS quota FROM mailbox ' 'WHERE username = \'%u\' AND active = \'1\'') config.dovecot_auth['disable_plaintext_auth'] = 'yes' config.dovecot_auth['auth_mechanisms'] = 'plain login' rm = '' for x in config.dovecot_auth: if x.startswith('include') and config.dovecot_auth[ x] != 'auth-sql.conf.ext': rm = x if rm: del config.dovecot_auth[rm] config.dovecot_auth['include_0'] = 'auth-sql.conf.ext' config.dovecot_ssl['ssl_key'] = '' config.dovecot_ssl['ssl_cert'] = '' # Tell Dovecot where to put its mail and how to save/access it config.dovecot_mail['mail_location'] = 'maildir:/var/vmail/%d/%n' config.dovecot_mail['mail_uid'] = 'vmail' config.dovecot_mail['mail_gid'] = 'vmail' config.dovecot_mail['first_valid_uid'] = str(uid) config.dovecot_mail['last_valid_uid'] = str(uid) # Tell Dovecot to communicate with Postfix (MTA) config.dovecot_master['service auth_0'] = { 'unix_listener auth-userdb_0': { 'mode': '0600', 'user': '******', 'group': 'vmail' }, 'unix_listener /var/spool/postfix/private/auth_0': { 'mode': '0660', 'user': '******', 'group': 'postfix' } } # Protect Dovecot configuration folder for r, d, f in os.walk('/etc/dovecot'): for x in d: os.chown(os.path.join(r, x), uid, pfgid) st = os.stat(os.path.join(r, x)) os.chmod( os.path.join(r, x), st.st_mode & ~stat.S_IROTH & ~stat.S_IWOTH & ~stat.S_IXOTH) for x in f: os.chown(os.path.join(r, x), uid, pfgid) st = os.stat(os.path.join(r, x)) os.chmod( os.path.join(r, x), st.st_mode & ~stat.S_IROTH & ~stat.S_IWOTH & ~stat.S_IXOTH) # Tell Postfix (MTA) how to get mailbox, alias and domain info # from our SQLite3 database f = open('/etc/postfix/sqlite_virtual_alias_domainaliases_maps.cf', 'w') f.write( 'dbpath = /var/lib/sqlite3/vmail.db\n' 'query = SELECT goto FROM alias,alias_domain\n' ' WHERE alias_domain.alias_domain = \'%d\'\n' ' AND alias.address = \'%u\' || \'@\' || alias_domain.target_domain\n' ' AND alias.active = 1\n') f.close() f = open('/etc/postfix/sqlite_virtual_alias_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'table = alias\n' 'select_field = goto\n' 'where_field = address\n' 'additional_conditions = and active = \'1\'\n') f.close() f = open('/etc/postfix/sqlite_virtual_domains_maps.cf', 'w') f.write( 'dbpath = /var/lib/sqlite3/vmail.db\n' 'table = domain\n' 'select_field = domain\n' 'where_field = domain\n' 'additional_conditions = and backupmx = \'0\' and active = \'1\'\n' ) f.close() f = open('/etc/postfix/sqlite_virtual_mailbox_domainaliases_maps.cf', 'w') f.write( 'dbpath = /var/lib/sqlite3/vmail.db\n' 'query = SELECT maildir FROM mailbox, alias_domain\n' ' WHERE alias_domain.alias_domain = \'%d\'\n' ' AND mailbox.username = \'%u\' || \'@\' || alias_domain.target_domain\n' ' AND mailbox.active = 1\n') f.close() f = open('/etc/postfix/sqlite_virtual_mailbox_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'table = mailbox\n' 'select_field = domain || \'/\' || local_part\n' 'where_field = username\n' 'additional_conditions = and active = \'1\'\n') f.close() f = open('/etc/postfix/header_checks', 'w') f.write('/^Received:/ IGNORE\n' '/^User-Agent:/ IGNORE\n' '/^X-Mailer:/ IGNORE\n' '/^X-Originating-IP:/ IGNORE\n' '/^x-cr-[a-z]*:/ IGNORE\n' '/^Thread-Index:/ IGNORE\n') f.close() # Configure Postfix config.postfix_main = { 'smtpd_banner': '$myhostname ESMTP $mail_name', 'biff': 'no', 'append_dot_mydomain': 'no', 'readme_directory': 'no', 'smtpd_sasl_type': 'dovecot', 'smtpd_sasl_path': 'private/auth', 'smtpd_sasl_auth_enable': 'yes', 'broken_sasl_auth_clients': 'yes', 'smtpd_sasl_security_options': 'noanonymous', 'smtpd_sasl_local_domain': '', 'smtpd_sasl_authenticated_header': 'yes', 'smtp_tls_note_starttls_offer': 'no', 'smtpd_tls_loglevel': '1', 'smtpd_tls_received_header': 'yes', 'smtpd_tls_session_cache_timeout': '3600s', 'tls_random_source': 'dev:/dev/urandom', 'smtpd_use_tls': 'no', 'smtpd_enforce_tls': 'no', 'smtp_use_tls': 'no', 'smtp_enforce_tls': 'no', 'smtpd_tls_security_level': 'may', 'smtp_tls_security_level': 'may', 'unknown_local_recipient_reject_code': '450', 'maximal_queue_lifetime': '7d', 'minimal_backoff_time': '1800s', 'maximal_backoff_time': '8000s', 'smtp_helo_timeout': '60s', 'smtpd_recipient_limit': '16', 'smtpd_soft_error_limit': '3', 'smtpd_hard_error_limit': '12', 'smtpd_helo_restrictions': 'permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit', 'smtpd_sender_restrictions': 'permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit', 'smtpd_client_restrictions': 'reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl', 'smtpd_recipient_restrictions': 'reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, permit', 'smtpd_data_restrictions': 'reject_unauth_pipelining', 'smtpd_relay_restrictions': 'reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, permit', 'smtpd_helo_required': 'yes', 'smtpd_delay_reject': 'yes', 'disable_vrfy_command': 'yes', 'myhostname': self.app.get_backend(IHostnameManager).gethostname().lower(), 'myorigin': self.app.get_backend(IHostnameManager).gethostname().lower(), 'mydestination': '', 'mynetworks': '127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128', 'mailbox_size_limit': '0', 'recipient_delimiter': '+', 'inet_interfaces': 'all', 'mynetworks_style': 'host', 'virtual_mailbox_base': '/var/vmail', 'virtual_mailbox_maps': 'sqlite:/etc/postfix/sqlite_virtual_mailbox_maps.cf, sqlite:/etc/postfix/sqlite_virtual_mailbox_domainaliases_maps.cf', 'virtual_uid_maps': 'static:' + str(uid), 'virtual_gid_maps': 'static:' + str(gid), 'virtual_alias_maps': 'sqlite:/etc/postfix/sqlite_virtual_alias_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domainaliases_maps.cf', 'virtual_mailbox_domains': 'sqlite:/etc/postfix/sqlite_virtual_domains_maps.cf', 'virtual_transport': 'dovecot', 'dovecot_destination_recipient_limit': '1', 'header_checks': 'regexp:/etc/postfix/header_checks', 'enable_original_recipient': 'no' } xs, xss, xd = False, False, False for x in config.postfix_master: if x[0] == 'smtp': x = ['smtp', 'inet', 'n', '-', '-', '-', '-', 'smtpd'] xs = True elif x[0] == 'submission': x = [ 'submission', 'inet', 'n', '-', '-', '-', '-', 'smtpd', '', 'syslog_name=postfix/submission', 'smtpd_sasl_auth_enable=yes', 'smtpd_tls_auth_only=yes', 'smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject', 'smtpd_sasl_security_options=noanonymous,noplaintext', 'smtpd_sasl_tls_security_options=noanonymous' ] xss = True elif x[0] == 'dovecot': x = [ 'dovecot', 'unix', '-', 'n', 'n', '-', '-', 'pipe', 'flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)' ] xd = True if not xs: config.postfix_master.insert( 0, ['smtp', 'inet', 'n', '-', '-', '-', '-', 'smtpd']) if not xss: config.postfix_master.insert(2, [ 'submission', 'inet', 'n', '-', '-', '-', '-', 'smtpd', '', 'syslog_name=postfix/submission', 'smtpd_sasl_auth_enable=yes', 'smtpd_tls_auth_only=yes', 'smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject', 'smtpd_sasl_security_options=noanonymous,noplaintext', 'smtpd_sasl_tls_security_options=noanonymous' ]) if not xd: config.postfix_master.append([ 'dovecot', 'unix', '-', 'n', 'n', '-', '-', 'pipe', 'flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)' ]) open('/etc/aliases', 'w').write('') # Save the configurations and start the services config.save(True) cfg = self.app.get_config(self) cfg.reinitialize = False cfg.save()
def on_init(self): self._tasks, self._others = backend.read_crontab(self._user) self._users = UsersBackend(self.app)
class CronPlugin(helpers.CategoryPlugin): text = 'Scheduled Tasks' iconfont = 'gen-alarm' folder = 'tools' def on_init(self): self._tasks, self._others = backend.read_crontab(self._user) self._users = UsersBackend(self.app) def on_session_start(self): self._user = shell('whoami').strip() backend.fix_crontab(self._user) self._labeltext = '' self._editing_task = -1 self._editing_other = -1 self._error = '' self._tasks = [] self._others = [] self._tab = 0 self._show_dialog = 0 self._show_dialog_user = 0 def get_ui(self): ui = self.app.inflate('cron:main') ui.find('tabs').set('active', self._tab) ui.find('title').set('text','Scheduled tasks for %s' % self._user) user_sel = [UI.DButtonItem(text=x.login, id='show/'+x.login) for x in sorted(self._users.get_users(), key=lambda x: x.uid)] ui.appendAll('users_select', *user_sel) table_other = ui.find("table_other") table_task = ui.find("table_task") #Fill non-task strings table for i, oth_str in enumerate(self._others): table_other.append(UI.DTR( UI.Label(text=oth_str), UI.DTD( UI.HContainer( UI.TipIcon(iconfont='gen-pencil-2', id='edit_oth/' + str(i), text='Edit'), UI.TipIcon(iconfont='gen-cancel-circle', id='del_oth/' + str(i), text='Delete', warning='Delete a string') ), hidden=True) )) #Fill tasks table for i, t in enumerate(self._tasks): table_task.append(UI.DTR( UI.Label(text=t.special if t.special else t.m), UI.Label(text=t.h if not t.special else ''), UI.Label(text=t.dom if not t.special else ''), UI.Label(text=t.mon if not t.special else ''), UI.Label(text=t.dow if not t.special else ''), UI.Label(text=t.command), UI.DTD( UI.TipIcon(iconfont='gen-cancel-circle', id='del_task/' + str(i), text='Delete', warning='Delete a task') ))) #if crontab return error part = self._error.partition(':')[2] self._error = 'Error:' + part if part else self._error if self._error: self.put_message('err', self._error) #For tabs name REGULARTAB = 11 ADVANCEDTAB = 12 SPECIALTAB = 13 #special values avaible_values = ('@reboot', '@hourly', '@daily', '@weekly', '@monthly', '@yearly') #edit or new task if self._editing_task != -1: task = backend.Task() ui.find('tabsEdit').set('active', REGULARTAB) ui.find('rreboot').set('checked', 'True') ui.find('m').set("value", task.m) ui.find('h').set("value", task.h) ui.find('dom').set("value", task.dom) ui.find('mon').set("value", task.mon) ui.find('dow').set("value", task.dow) #For templates ui.find('tabsRegular').set('active', 15) SelectOptionNumbs = lambda r: [UI.SelectOption(text=str(m), value=str(m)) for m in xrange(r)] #generate similar selectOptions lists for xml. minute_select_h = SelectOptionNumbs(60) minute_select_d = SelectOptionNumbs(60) minute_select_w = SelectOptionNumbs(60) minute_select_m = SelectOptionNumbs(60) hour_select_d = SelectOptionNumbs(24) hour_select_w = SelectOptionNumbs(24) hour_select_m = SelectOptionNumbs(24) weekday = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') weekday_select = [UI.SelectOption(text=str(w), value=str(v+1)) for v, w in enumerate(weekday)] day_select = [UI.SelectOption(text=str(d), value=str(d)) for d in range(1, 32)] #Fill selects ui.appendAll("minute_select_h", *minute_select_h) ui.appendAll("minute_select_d", *minute_select_d) ui.appendAll("minute_select_w", *minute_select_w) ui.appendAll("minute_select_m", *minute_select_m) ui.appendAll("hour_select_d", *hour_select_d) ui.appendAll("hour_select_w", *hour_select_w) ui.appendAll("hour_select_m", *hour_select_m) ui.appendAll("weekday_select", *weekday_select) ui.appendAll("day_select", *day_select) #Nothing happens with task else: ui.remove('dlgEditTask') #edit non-task string if self._editing_other != -1 and self._show_dialog: other_value = self._others[self._editing_other]\ if self._editing_other < len(self._others) else '' ui.find("other_str").set("value", other_value) #Nothing happens with non-task string else: ui.remove('dlgEditOther') return ui @event('button/click') @event('linklabel/click') def on_click(self, event, params, vars=None): if params[0] == 'show': self._user = params[1] backend.fix_crontab(self._user) self._tasks, self._others = backend.read_crontab(self._user) if params[0] == 'add_task': self._editing_task = len(self._tasks) self._show_dialog = 1 if params[0] == 'del_task': self._tasks.pop(int(params[1])) self._error = backend.write_crontab(self._others + self._tasks, self._user) if params[0] == 'add_oth': self._editing_other = len(self._others) self._show_dialog = 1 if params[0] == 'edit_oth': self._editing_other = int(params[1]) self._show_dialog = 1 if params[0] == 'del_oth': self._others.pop(int(params[1])) self._error = backend.write_crontab(self._others + self._tasks, self._user) self._tab = 1 @event('form/submit') def on_submit_form(self, event, params, vars=None): "For user select or Regular and advanced Task" if params[0] == 'frmAdvanced' and\ vars.getvalue('action') == 'OK': task_str = ' '.join(( vars.getvalue('m').replace(' ', '') or '*', vars.getvalue('h').replace(' ', '') or '*', vars.getvalue('dom').replace(' ', '') or '*', vars.getvalue('mon').replace(' ', '') or '*', vars.getvalue('dow').replace(' ', '') or '*' )) task_str += '\t' + vars.getvalue('a_command') if self.set_task(task_str): return 1 elif params[0] == 'frmSpecial' and\ vars.getvalue('action') == 'OK': task_str = '@' + vars.getvalue('special') task_str += '\t' + vars.getvalue('s_command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempMinutes' and\ vars.getvalue('action') == 'OK': task_str = '*/' + (vars.getvalue('minutes') or '1') task_str += ' * * * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempHours' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_h') + ' ' task_str += '*/' + (vars.getvalue('hours') or '1') task_str += ' * * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempDays' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_d') + ' ' task_str += vars.getvalue('hour_select_d') + ' ' task_str += '*/' + (vars.getvalue('days') or '1') task_str += ' * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempMonths' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_m') + ' ' task_str += vars.getvalue('hour_select_m') + ' ' task_str += vars.getvalue('day_select') + ' ' task_str += '*/' + (vars.getvalue('months') or '1') task_str += ' *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempWeek' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_w') + ' ' task_str += vars.getvalue('hour_select_w') + ' ' task_str += '* * ' task_str += vars.getvalue('weekday_select') task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 self._show_dialog = 0 self._editing_task = -1 self._tab = 0 def set_task(self, task_str): "Set new or edited task" #noinspection PyBroadException try: new_task = backend.Task(task_str) except: self._error = 'Error: Wrong options.' self._editing_task = -1 return 1 if self._editing_task < len(self._tasks): self._tasks[self._editing_task] = new_task else: self._tasks.append(new_task) self._error = backend.write_crontab(self._others + self._tasks, self._user) if self._error: self._tasks, self._others = backend.read_crontab() ConfManager.get().commit('cron') return 0 @event('dialog/submit') def on_submit_dlg(self, event, params, vars=None): " for submit non-task string. It is use dialog" if params[0] == 'dlgEditOther': if vars.getvalue('action') == 'OK': if self._editing_other < len(self._others): self._others[self._editing_other] = vars.getvalue('other_str') else: self._others.append(vars.getvalue('other_str')) self._error = backend.write_crontab(self._others + self._tasks, self._user) if self._error: self._tasks, self._others = backend.read_crontab() self._show_dialog = 0 self._editing_other = -1 self._tab = 1
def post_install(self, name, path, vars, dbinfo={}): UsersBackend(self.app).add_user('etherpad') # Create/Edit the config file cfg = { "title": "Etherpad", "favicon": "favicon.ico", "ip": "127.0.0.1", "port": "2369", "sessionKey": hashlib.sha1(str(random.random())).hexdigest(), "dbType": "mysql", "dbSettings": { "user": dbinfo['user'], "host": "localhost", "password": dbinfo['passwd'], "database": dbinfo['name'] }, "defaultPadText": ("Welcome to Etherpad on arkOS!\n\nThis pad text is " "synchronized as you type, so that everyone viewing this page " "sees the same text. This allows you to collaborate seamlessly " "on documents!\n\nGet involved with Etherpad at " "http://etherpad.org, or with arkOS at http://arkos.io\n"), "requireSession": False, "editOnly": False, "minify": True, "maxAge": 60 * 60 * 6, "abiword": None, "requireAuthentication": False, "requireAuthorization": False, "trustProxy": True, "disableIPlogging": False, "socketTransportProtocols": ["xhr-polling", "jsonp-polling", "htmlfile"], "loglevel": "INFO", "logconfig": { "appenders": [{ "type": "console" }] }, "users": { vars.getvalue('ether_admin'): { "password": vars.getvalue('ether_pass'), "is_admin": True }, }, } with open(os.path.join(path, 'settings.json'), 'w') as f: json.dump(cfg, f, indent=4) # node-gyp needs the HOME variable to be set with open(os.path.join(path, 'bin/run.sh')) as f: run_script = f.readlines() run_script.insert(1, "export HOME=%s" % path) with open(os.path.join(path, 'bin/run.sh'), 'w') as f: f.writelines(run_script) # Install deps right away if not shell(os.path.join(path, 'bin/installDeps.sh') + ' || exit 1'): raise RuntimeError("Etherpad dependencies could not be installed.") # Install selected plugins mods = list( # e.g. "ep_plugin/ep_adminpads" str(var).split("/")[1] # ^^^^^^^^^^^^ for var in vars if var.startswith('ep_plugin/') and int(vars.getvalue(var))) if mods: mod_inst_path = os.path.join(path, "node_modules") if not os.path.exists(mod_inst_path): os.mkdir(mod_inst_path) nodectl = apis.langassist(self.app).get_interface('NodeJS') nodectl.install(*mods, install_path=mod_inst_path) # Make supervisor entry s = self.app.get_backend(apis.services.IServiceManager) s.edit( 'etherpad', { 'stype': 'program', 'directory': path, 'user': '******', 'command': os.path.join(path, 'bin/run.sh'), 'autostart': 'true', 'autorestart': 'true', 'stdout_logfile': '/var/log/etherpad.log', 'stderr_logfile': '/var/log/etherpad.log' }) s.enable('etherpad', 'supervisor') # Change owner of everything in the etherpad path shell('chown -R etherpad ' + path)
def post_remove(self, site): UsersBackend(self.app).del_user('etherpad') self.app.get_backend(apis.services.IServiceManager).delete( 'etherpad', 'supervisor')
def post_remove(self, name): users = UsersBackend(self.app) users.del_user('ghost') s = apis.orders(self.app).get_interface('supervisor') if s: s[0].order('del', 'ghost')
def post_install(self, name, path, vars): nodectl = apis.langassist(self.app).get_interface('NodeJS') users = UsersBackend(self.app) if not os.path.exists('/usr/bin/python') and os.path.exists('/usr/bin/python'): os.symlink('/usr/bin/python2', '/usr/bin/python') # A bug in 0.4.1 prevents [email protected] from installing properly. # Fallback to 2.1.15 d = json.loads(open(os.path.join(path, 'package.json'), 'r').read()) d['dependencies']['sqlite3'] = '2.1.15' open(os.path.join(path, 'package.json'), 'w').write(json.dumps(d)) nodectl.install_from_package(path, 'production') users.add_user('ghost') s = apis.orders(self.app).get_interface('supervisor') if s: s[0].order('new', 'ghost', 'program', [('directory', path), ('user', 'ghost'), ('command', 'node %s'%os.path.join(path, 'index.js')), ('autostart', 'true'), ('autorestart', 'true'), ('environment', 'NODE_ENV="production"'), ('stdout_logfile', '/var/log/ghost.log'), ('stderr_logfile', '/var/log/ghost.log')]) addr = vars.getvalue('addr', 'localhost') port = vars.getvalue('port', '80') # Get Mail settings mail_settings = { 'transport' : vars.getvalue('ghost-transport', ''), 'service' : vars.getvalue('ghost-service', ''), 'mail_user' : vars.getvalue('ghost-mail-user', ''), 'mail_pass' : vars.getvalue('ghost-mail-pass', ''), 'from_address' : vars.getvalue('ghost-from-address', '') } # Create/Edit the Ghost config file f = open(os.path.join(path, 'config.example.js'), 'r').read() with open(os.path.join(path, 'config.js'), 'w') as config_file: f = f.replace('http://my-ghost-blog.com', 'http://'+addr+(':'+port if port != '80' else'')) if len(set(mail_settings.values())) != 1 and\ mail_settings['transport'] != '': # If the mail settings exist, add them f = f.replace( "mail: {},",\ 'mail: {\n' "\tfromaddress: '" + mail_settings['from_address'] + "',\n" "\ttransport: '" + mail_settings['transport'] + "',\n" "\t\toptions: {\n" "\t\t\tservice: '" + mail_settings['service'] + "',\n" "\t\t\tauth: {\n" "\t\t\t\tuser: '******'mail_user'] + "',\n" "\t\t\t\tpass: '******'mail_pass'] + "'\n" "\t\t\t}\n" "\t\t}\n" "},\n" ) config_file.write(f) config_file.close() # Finally, make sure that permissions are set so that Ghost # can make adjustments and save plugins when need be. shell('chown -R ghost ' + path)
x.write(chain) x.close() open(os.path.join('/etc/ssl/private/genesis', name + '.key'), 'w').write(key) if ky.type() == OpenSSL.crypto.TYPE_RSA: keytype = 'RSA' elif ky.type() == OpenSSL.crypto.TYPE_DSA: keytype = 'DSA' else: keytype = 'Unknown' try: gid = grp.getgrnam('ssl-cert').gr_gid except KeyError: UsersBackend(self.app).add_group('ssl-cert') gid = grp.getgrnam('ssl-cert').gr_gid os.chown(os.path.join('/etc/ssl/certs/genesis', name + '.crt'), -1, gid) os.chmod(os.path.join('/etc/ssl/certs/genesis', name + '.crt'), 0660) os.chown(os.path.join('/etc/ssl/private/genesis', name + '.key'), -1, gid) os.chmod(os.path.join('/etc/ssl/private/genesis', name + '.key'), 0660) def gencert(self, name, vars, hostname): # Make sure our folders are in place if not os.path.exists('/etc/ssl/certs/genesis'): os.mkdir('/etc/ssl/certs/genesis') if not os.path.exists('/etc/ssl/private/genesis'): os.mkdir('/etc/ssl/private/genesis')
class CronPlugin(helpers.CategoryPlugin): text = 'Scheduled Tasks' iconfont = 'gen-alarm' folder = 'tools' def on_init(self): self._tasks, self._others = backend.read_crontab(self._user) self._users = UsersBackend(self.app) def on_session_start(self): self._user = shell('whoami').strip() backend.fix_crontab(self._user) self._labeltext = '' self._editing_task = -1 self._editing_other = -1 self._error = '' self._tasks = [] self._others = [] self._tab = 0 self._show_dialog = 0 self._show_dialog_user = 0 def get_ui(self): ui = self.app.inflate('cron:main') ui.find('tabs').set('active', self._tab) ui.find('title').set('text', 'Scheduled tasks for %s' % self._user) user_sel = [ UI.DButtonItem(text=x.login, id='show/' + x.login) for x in sorted(self._users.get_users(), key=lambda x: x.uid) ] ui.appendAll('users_select', *user_sel) table_other = ui.find("table_other") table_task = ui.find("table_task") #Fill non-task strings table for i, oth_str in enumerate(self._others): table_other.append( UI.DTR( UI.Label(text=oth_str), UI.DTD(UI.HContainer( UI.TipIcon(iconfont='gen-pencil-2', id='edit_oth/' + str(i), text='Edit'), UI.TipIcon(iconfont='gen-cancel-circle', id='del_oth/' + str(i), text='Delete', warning='Delete a string')), hidden=True))) #Fill tasks table for i, t in enumerate(self._tasks): table_task.append( UI.DTR( UI.Label(text=t.special if t.special else t.m), UI.Label(text=t.h if not t.special else ''), UI.Label(text=t.dom if not t.special else ''), UI.Label(text=t.mon if not t.special else ''), UI.Label(text=t.dow if not t.special else ''), UI.Label(text=t.command), UI.DTD( UI.TipIcon(iconfont='gen-cancel-circle', id='del_task/' + str(i), text='Delete', warning='Delete a task')))) #if crontab return error part = self._error.partition(':')[2] self._error = 'Error:' + part if part else self._error if self._error: self.put_message('err', self._error) #For tabs name REGULARTAB = 11 ADVANCEDTAB = 12 SPECIALTAB = 13 #special values avaible_values = ('@reboot', '@hourly', '@daily', '@weekly', '@monthly', '@yearly') #edit or new task if self._editing_task != -1: task = backend.Task() ui.find('tabsEdit').set('active', REGULARTAB) ui.find('rreboot').set('checked', 'True') ui.find('m').set("value", task.m) ui.find('h').set("value", task.h) ui.find('dom').set("value", task.dom) ui.find('mon').set("value", task.mon) ui.find('dow').set("value", task.dow) #For templates ui.find('tabsRegular').set('active', 15) SelectOptionNumbs = lambda r: [ UI.SelectOption(text=str(m), value=str(m)) for m in xrange(r) ] #generate similar selectOptions lists for xml. minute_select_h = SelectOptionNumbs(60) minute_select_d = SelectOptionNumbs(60) minute_select_w = SelectOptionNumbs(60) minute_select_m = SelectOptionNumbs(60) hour_select_d = SelectOptionNumbs(24) hour_select_w = SelectOptionNumbs(24) hour_select_m = SelectOptionNumbs(24) weekday = ('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday') weekday_select = [ UI.SelectOption(text=str(w), value=str(v + 1)) for v, w in enumerate(weekday) ] day_select = [ UI.SelectOption(text=str(d), value=str(d)) for d in range(1, 32) ] #Fill selects ui.appendAll("minute_select_h", *minute_select_h) ui.appendAll("minute_select_d", *minute_select_d) ui.appendAll("minute_select_w", *minute_select_w) ui.appendAll("minute_select_m", *minute_select_m) ui.appendAll("hour_select_d", *hour_select_d) ui.appendAll("hour_select_w", *hour_select_w) ui.appendAll("hour_select_m", *hour_select_m) ui.appendAll("weekday_select", *weekday_select) ui.appendAll("day_select", *day_select) #Nothing happens with task else: ui.remove('dlgEditTask') #edit non-task string if self._editing_other != -1 and self._show_dialog: other_value = self._others[self._editing_other]\ if self._editing_other < len(self._others) else '' ui.find("other_str").set("value", other_value) #Nothing happens with non-task string else: ui.remove('dlgEditOther') return ui @event('button/click') @event('linklabel/click') def on_click(self, event, params, vars=None): if params[0] == 'show': self._user = params[1] backend.fix_crontab(self._user) self._tasks, self._others = backend.read_crontab(self._user) if params[0] == 'add_task': self._editing_task = len(self._tasks) self._show_dialog = 1 if params[0] == 'del_task': self._tasks.pop(int(params[1])) self._error = backend.write_crontab(self._others + self._tasks, self._user) if params[0] == 'add_oth': self._editing_other = len(self._others) self._show_dialog = 1 if params[0] == 'edit_oth': self._editing_other = int(params[1]) self._show_dialog = 1 if params[0] == 'del_oth': self._others.pop(int(params[1])) self._error = backend.write_crontab(self._others + self._tasks, self._user) self._tab = 1 @event('form/submit') def on_submit_form(self, event, params, vars=None): "For user select or Regular and advanced Task" if params[0] == 'frmAdvanced' and\ vars.getvalue('action') == 'OK': task_str = ' '.join( (vars.getvalue('m').replace(' ', '') or '*', vars.getvalue('h').replace(' ', '') or '*', vars.getvalue('dom').replace(' ', '') or '*', vars.getvalue('mon').replace(' ', '') or '*', vars.getvalue('dow').replace(' ', '') or '*')) task_str += '\t' + vars.getvalue('a_command') if self.set_task(task_str): return 1 elif params[0] == 'frmSpecial' and\ vars.getvalue('action') == 'OK': task_str = '@' + vars.getvalue('special') task_str += '\t' + vars.getvalue('s_command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempMinutes' and\ vars.getvalue('action') == 'OK': task_str = '*/' + (vars.getvalue('minutes') or '1') task_str += ' * * * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempHours' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_h') + ' ' task_str += '*/' + (vars.getvalue('hours') or '1') task_str += ' * * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempDays' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_d') + ' ' task_str += vars.getvalue('hour_select_d') + ' ' task_str += '*/' + (vars.getvalue('days') or '1') task_str += ' * *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempMonths' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_m') + ' ' task_str += vars.getvalue('hour_select_m') + ' ' task_str += vars.getvalue('day_select') + ' ' task_str += '*/' + (vars.getvalue('months') or '1') task_str += ' *' task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 elif params[0] == 'frmTempWeek' and\ vars.getvalue('action') == 'OK': task_str = vars.getvalue('minute_select_w') + ' ' task_str += vars.getvalue('hour_select_w') + ' ' task_str += '* * ' task_str += vars.getvalue('weekday_select') task_str += '\t' + vars.getvalue('command') if self.set_task(task_str): return 1 self._show_dialog = 0 self._editing_task = -1 self._tab = 0 def set_task(self, task_str): "Set new or edited task" #noinspection PyBroadException try: new_task = backend.Task(task_str) except: self._error = 'Error: Wrong options.' self._editing_task = -1 return 1 if self._editing_task < len(self._tasks): self._tasks[self._editing_task] = new_task else: self._tasks.append(new_task) self._error = backend.write_crontab(self._others + self._tasks, self._user) if self._error: self._tasks, self._others = backend.read_crontab() ConfManager.get().commit('cron') return 0 @event('dialog/submit') def on_submit_dlg(self, event, params, vars=None): " for submit non-task string. It is use dialog" if params[0] == 'dlgEditOther': if vars.getvalue('action') == 'OK': if self._editing_other < len(self._others): self._others[self._editing_other] = vars.getvalue( 'other_str') else: self._others.append(vars.getvalue('other_str')) self._error = backend.write_crontab(self._others + self._tasks, self._user) if self._error: self._tasks, self._others = backend.read_crontab() self._show_dialog = 0 self._editing_other = -1 self._tab = 1
def initial_setup(self): # Grab frameworks for use later config = MailConfig(self.app) users = UsersBackend(self.app) dbase = apis.databases(self.app).get_interface('SQLite3') config.load() # Create a SQLite3 database for storing mailbox, alias and # domain information if 'vmail' in [x['name'] for x in dbase.get_dbs()]: dbase.remove('vmail') dbase.add('vmail') sql = ('CREATE TABLE "alias" (' 'address varchar(255) NOT NULL default "", ' 'goto text NOT NULL, domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (address)); ' 'CREATE TABLE "domain" ( ' 'domain varchar(255) NOT NULL default "", ' 'transport varchar(255) default NULL, ' 'backupmx tinyint(1) NOT NULL default "0", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (domain)); ' 'CREATE TABLE "alias_domain" ( ' 'alias_domain varchar(255) NOT NULL default "", ' 'target_domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (alias_domain)); ' 'CREATE TABLE "mailbox" ( ' 'username varchar(255) NOT NULL default "", ' 'password varchar(255) NOT NULL default "", ' 'name varchar(255) NOT NULL default "", ' 'maildir varchar(255) NOT NULL default "", ' 'quota bigint(20) NOT NULL default "0", ' 'local_part varchar(255) NOT NULL default "", ' 'domain varchar(255) NOT NULL default "", ' 'created datetime NOT NULL default "0000-00-00 00:00:00", ' 'active tinyint(1) NOT NULL default "1", ' 'PRIMARY KEY (username));' 'CREATE INDEX address ON alias (address);' 'CREATE INDEX active ON alias_domain (active);' 'CREATE INDEX target_domain ON alias_domain (target_domain);' 'CREATE INDEX username ON mailbox (username);' ) dbase.execute('vmail', sql) # Add system user and group for handling mail users.add_sys_user('vmail') users.add_group('vmail') users.add_to_group('vmail', 'vmail') uid = int(users.get_user('vmail', users.get_all_users()).uid) gid = int(users.get_group('vmail', users.get_all_groups()).gid) pfgid = int(users.get_group('dovecot', users.get_all_groups()).gid) # Create the virtual mail directory if not os.path.exists('/var/vmail'): os.mkdir('/var/vmail') users.change_user_param('vmail', 'home', '/var/vmail') users.change_user_param('vmail', 'shell', '/sbin/nologin') os.chmod('/var/vmail', 0770) os.chown('/var/vmail', uid, gid) # Tell Dovecot (MDA) where to find users and passwords config.dovecot_authsql = { 'passdb_0': { 'driver': 'sql', 'args': '/etc/dovecot/dovecot-sql.conf.ext' }, 'userdb_0': { 'driver': 'sql', 'args': '/etc/dovecot/dovecot-sql.conf.ext' } } # Tell Dovecot how to read our SQL config.dovecot_dovecotsql['driver'] = 'sqlite' config.dovecot_dovecotsql['connect'] = '/var/lib/sqlite3/vmail.db' config.dovecot_dovecotsql['default_pass_scheme'] = 'MD5-CRYPT' config.dovecot_dovecotsql['password_query'] = ( 'SELECT username as user, password, \'/var/vmail/%d/%n\'' ' as userdb_home, \'maildir:/var/vmail/%d/%n\' as userdb_mail,' ' '+str(uid)+' as userdb_uid, '+str(gid)+' as userdb_gid FROM mailbox ' 'WHERE username = \'%u\' AND active = \'1\'') config.dovecot_dovecotsql['user_query'] = ( 'SELECT \'/var/vmail/%d/%n\' as home, ' '\'maildir:/var/vmail/%d/%n\' as mail, '+str(uid)+' AS uid, '+str(gid)+' AS gid, ' '\'dirsize:storage=\'|| quota AS quota FROM mailbox ' 'WHERE username = \'%u\' AND active = \'1\'') config.dovecot_auth['disable_plaintext_auth'] = 'yes' config.dovecot_auth['auth_mechanisms'] = 'plain login' rm = '' for x in config.dovecot_auth: if x.startswith('include') and config.dovecot_auth[x] != 'auth-sql.conf.ext': rm = x if rm: del config.dovecot_auth[rm] config.dovecot_auth['include_0'] = 'auth-sql.conf.ext' config.dovecot_ssl['ssl_key'] = '' config.dovecot_ssl['ssl_cert'] = '' # Tell Dovecot where to put its mail and how to save/access it config.dovecot_mail['mail_location'] = 'maildir:/var/vmail/%d/%n' config.dovecot_mail['mail_uid'] = 'vmail' config.dovecot_mail['mail_gid'] = 'vmail' config.dovecot_mail['first_valid_uid'] = str(uid) config.dovecot_mail['last_valid_uid'] = str(uid) # Tell Dovecot to communicate with Postfix (MTA) config.dovecot_master['service auth_0'] = { 'unix_listener auth-userdb_0': { 'mode': '0600', 'user': '******', 'group': 'vmail' }, 'unix_listener /var/spool/postfix/private/auth_0': { 'mode': '0660', 'user': '******', 'group': 'postfix' } } # Protect Dovecot configuration folder for r, d, f in os.walk('/etc/dovecot'): for x in d: os.chown(os.path.join(r, x), uid, pfgid) st = os.stat(os.path.join(r, x)) os.chmod(os.path.join(r, x), st.st_mode&~stat.S_IROTH&~stat.S_IWOTH&~stat.S_IXOTH) for x in f: os.chown(os.path.join(r, x), uid, pfgid) st = os.stat(os.path.join(r, x)) os.chmod(os.path.join(r, x), st.st_mode&~stat.S_IROTH&~stat.S_IWOTH&~stat.S_IXOTH) # Tell Postfix (MTA) how to get mailbox, alias and domain info # from our SQLite3 database f = open('/etc/postfix/sqlite_virtual_alias_domainaliases_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'query = SELECT goto FROM alias,alias_domain\n' ' WHERE alias_domain.alias_domain = \'%d\'\n' ' AND alias.address = \'%u\' || \'@\' || alias_domain.target_domain\n' ' AND alias.active = 1\n') f.close() f = open('/etc/postfix/sqlite_virtual_alias_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'table = alias\n' 'select_field = goto\n' 'where_field = address\n' 'additional_conditions = and active = \'1\'\n') f.close() f = open('/etc/postfix/sqlite_virtual_domains_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'table = domain\n' 'select_field = domain\n' 'where_field = domain\n' 'additional_conditions = and backupmx = \'0\' and active = \'1\'\n') f.close() f = open('/etc/postfix/sqlite_virtual_mailbox_domainaliases_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'query = SELECT maildir FROM mailbox, alias_domain\n' ' WHERE alias_domain.alias_domain = \'%d\'\n' ' AND mailbox.username = \'%u\' || \'@\' || alias_domain.target_domain )\n' ' AND mailbox.active = 1\n') f.close() f = open('/etc/postfix/sqlite_virtual_mailbox_maps.cf', 'w') f.write('dbpath = /var/lib/sqlite3/vmail.db\n' 'table = mailbox\n' 'select_field = domain || \'/\' || local_part)\n' 'where_field = username\n' 'additional_conditions = and active = \'1\'\n') f.close() f = open('/etc/postfix/header_checks', 'w') f.write('/^Received:/ IGNORE\n' '/^User-Agent:/ IGNORE\n' '/^X-Mailer:/ IGNORE\n' '/^X-Originating-IP:/ IGNORE\n' '/^x-cr-[a-z]*:/ IGNORE\n' '/^Thread-Index:/ IGNORE\n') f.close() # Configure Postfix config.postfix_main = { 'smtpd_banner': '$myhostname ESMTP $mail_name', 'biff': 'no', 'append_dot_mydomain': 'no', 'readme_directory': 'no', 'smtpd_sasl_type': 'dovecot', 'smtpd_sasl_path': 'private/auth', 'smtpd_sasl_auth_enable': 'yes', 'broken_sasl_auth_clients': 'yes', 'smtpd_sasl_security_options': 'noanonymous', 'smtpd_sasl_local_domain': '', 'smtpd_sasl_authenticated_header': 'yes', 'smtp_tls_note_starttls_offer': 'no', 'smtpd_tls_loglevel': '1', 'smtpd_tls_received_header': 'yes', 'smtpd_tls_session_cache_timeout': '3600s', 'tls_random_source': 'dev:/dev/urandom', 'smtpd_use_tls': 'no', 'smtpd_enforce_tls': 'no', 'smtp_use_tls': 'no', 'smtp_enforce_tls': 'no', 'smtpd_tls_security_level': 'may', 'smtp_tls_security_level': 'may', 'unknown_local_recipient_reject_code': '450', 'maximal_queue_lifetime': '7d', 'minimal_backoff_time': '1800s', 'maximal_backoff_time': '8000s', 'smtp_helo_timeout': '60s', 'smtpd_recipient_limit': '16', 'smtpd_soft_error_limit': '3', 'smtpd_hard_error_limit': '12', 'smtpd_helo_restrictions': 'permit_mynetworks, warn_if_reject reject_non_fqdn_hostname, reject_invalid_hostname, permit', 'smtpd_sender_restrictions': 'permit_sasl_authenticated, permit_mynetworks, warn_if_reject reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unauth_pipelining, permit', 'smtpd_client_restrictions': 'reject_rbl_client sbl.spamhaus.org, reject_rbl_client blackholes.easynet.nl', 'smtpd_recipient_restrictions': 'reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, permit', 'smtpd_data_restrictions': 'reject_unauth_pipelining', 'smtpd_relay_restrictions': 'reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unauth_destination, permit', 'smtpd_helo_required': 'yes', 'smtpd_delay_reject': 'yes', 'disable_vrfy_command': 'yes', 'myhostname': self.app.get_backend(IHostnameManager).gethostname().lower(), 'myorigin': self.app.get_backend(IHostnameManager).gethostname().lower(), 'mydestination': '', 'mynetworks': '127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128', 'mailbox_size_limit': '0', 'recipient_delimiter': '+', 'inet_interfaces': 'all', 'mynetworks_style': 'host', 'virtual_mailbox_base': '/var/vmail', 'virtual_mailbox_maps': 'sqlite:/etc/postfix/sqlite_virtual_mailbox_maps.cf, sqlite:/etc/postfix/sqlite_virtual_mailbox_domainaliases_maps.cf', 'virtual_uid_maps': 'static:'+str(uid), 'virtual_gid_maps': 'static:'+str(gid), 'virtual_alias_maps': 'sqlite:/etc/postfix/sqlite_virtual_alias_maps.cf, sqlite:/etc/postfix/sqlite_virtual_alias_domainaliases_maps.cf', 'virtual_mailbox_domains': 'sqlite:/etc/postfix/sqlite_virtual_domains_maps.cf', 'virtual_transport': 'dovecot', 'dovecot_destination_recipient_limit': '1', 'header_checks': 'regexp:/etc/postfix/header_checks', 'enable_original_recipient': 'no' } xs, xss, xd = False, False, False for x in config.postfix_master: if x[0] == 'smtp': x = ['smtp', 'inet', 'n', '-', '-', '-', '-', 'smtpd'] xs = True elif x[0] == 'submission': x = ['submission', 'inet', 'n', '-', '-', '-', '-', 'smtpd', '', 'syslog_name=postfix/submission', 'smtpd_sasl_auth_enable=yes', 'smtpd_tls_auth_only=yes', 'smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject', 'smtpd_sasl_security_options=noanonymous,noplaintext', 'smtpd_sasl_tls_security_options=noanonymous'] xss = True elif x[0] == 'dovecot': x = ['dovecot', 'unix', '-', 'n', 'n', '-', '-', 'pipe', 'flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)'] xd = True if not xs: config.postfix_master.insert(0, ['smtp', 'inet', 'n', '-', '-', '-', '-', 'smtpd']) if not xss: config.postfix_master.insert(2, ['submission', 'inet', 'n', '-', '-', '-', '-', 'smtpd', '', 'syslog_name=postfix/submission', 'smtpd_sasl_auth_enable=yes', 'smtpd_tls_auth_only=yes', 'smtpd_client_restrictions=permit_sasl_authenticated,reject_unauth_destination,reject', 'smtpd_sasl_security_options=noanonymous,noplaintext', 'smtpd_sasl_tls_security_options=noanonymous']) if not xd: config.postfix_master.append(['dovecot', 'unix', '-', 'n', 'n', '-', '-', 'pipe', 'flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/dovecot-lda -d $(recipient)']) open('/etc/aliases', 'w').write('') # Save the configurations and start the services config.save(True) cfg = self.app.get_config(self) cfg.reinitialize = False cfg.save()
def post_remove(self, site): users = UsersBackend(self.app) users.del_user('ghost') s = self.app.get_backend(apis.services.IServiceManager) s.delete('ghost', 'supervisor')
def post_install(self, name, path, vars, dbinfo={}): nodectl = apis.langassist(self.app).get_interface('NodeJS') users = UsersBackend(self.app) if not os.path.exists('/usr/bin/python') and os.path.exists( '/usr/bin/python'): os.symlink('/usr/bin/python2', '/usr/bin/python') d = json.loads(open(os.path.join(path, 'package.json'), 'r').read()) del d['dependencies']['bcryptjs'] d['dependencies']['bcrypt'] = '0.7.8' open(os.path.join(path, 'package.json'), 'w').write(json.dumps(d)) d = open(os.path.join(path, 'core/server/models/user.js'), 'r').read() d = d.replace('bcryptjs', 'bcrypt') open(os.path.join(path, 'core/server/models/user.js'), 'w').write(d) nodectl.install_from_package(path, 'production', { 'sqlite': '/usr/bin', 'python': '/usr/bin/python2' }) users.add_user('ghost') s = self.app.get_backend(apis.services.IServiceManager) s.edit( 'ghost', { 'stype': 'program', 'directory': path, 'user': '******', 'command': 'node %s' % os.path.join(path, 'index.js'), 'autostart': 'true', 'autorestart': 'true', 'environment': 'NODE_ENV="production"', 'stdout_logfile': '/var/log/ghost.log', 'stderr_logfile': '/var/log/ghost.log' }) s.enable('ghost', 'supervisor') addr = vars.getvalue('addr', 'localhost') port = vars.getvalue('port', '80') # Get Mail settings mail_settings = { 'transport': vars.getvalue('ghost-transport', ''), 'service': vars.getvalue('ghost-service', ''), 'mail_user': vars.getvalue('ghost-mail-user', ''), 'mail_pass': vars.getvalue('ghost-mail-pass', ''), 'from_address': vars.getvalue('ghost-from-address', '') } # Create/Edit the Ghost config file f = open(os.path.join(path, 'config.example.js'), 'r').read() with open(os.path.join(path, 'config.js'), 'w') as config_file: f = f.replace( 'http://my-ghost-blog.com', 'http://' + addr + (':' + port if port != '80' else '')) if len(set(mail_settings.values())) != 1 and\ mail_settings['transport'] != '': # If the mail settings exist, add them f = f.replace( "mail: {},",\ 'mail: {\n' "\tfromaddress: '" + mail_settings['from_address'] + "',\n" "\ttransport: '" + mail_settings['transport'] + "',\n" "\t\toptions: {\n" "\t\t\tservice: '" + mail_settings['service'] + "',\n" "\t\t\tauth: {\n" "\t\t\t\tuser: '******'mail_user'] + "',\n" "\t\t\t\tpass: '******'mail_pass'] + "'\n" "\t\t\t}\n" "\t\t}\n" "},\n" ) config_file.write(f) config_file.close() # Finally, make sure that permissions are set so that Ghost # can make adjustments and save plugins when need be. shell('chown -R ghost ' + path)
def get_main_ui(self): ui = self.app.inflate('samba:main') ui.find('tabs').set('active', self._tab) # Shares for h in self._cfg.get_shares(): r = UI.DTR( UI.IconFont(iconfont='gen-folder'), UI.Label(text=h), UI.Label(text=self._cfg.shares[h]['path']), UI.HContainer( UI.TipIcon(iconfont='gen-pencil-2', text='Edit', id='editshare/' + h), UI.TipIcon( iconfont='gen-close', text='Delete', id='delshare/' + h, warning='Are you sure you want to delete the %s share?' % h)), ) ui.append('shares', r) if not self._editing_share is None: if self._editing_share == '': ui.append('main', self.get_ui_edit_share()) else: ui.append( 'main', self.get_ui_edit_share( self._cfg.shares[self._editing_share])) # Users for h in sorted(self._cfg.users.keys()): r = UI.DTR( UI.IconFont(iconfont='gen-user'), UI.Label(text=h), UI.HContainer( #UI.TipIcon(iconfont='gen-pencil-2', # text='Edit', id='edituser/' + h), UI.TipIcon( iconfont='gen-close', text='Delete', id='deluser/' + h, warning= 'Are you sure you want to delete %s from the Samba users list?' % h)), ) ui.append('users', r) #if not self._editing_user is None: # if self._editing_user == '': # ui.append('main', self.get_ui_edit_user()) # else: # if not self._editing_user in self._cfg.users.keys(): # self.put_message('err', 'User not found') # self._editing_user = None # else: # ui.append('main', self.get_ui_edit_user( # self._cfg.users[self._editing_user] # )) if not self._editing is None: ui.append( 'main', UI.InputBox( title=self._editing, value=self._cfg.users[self._editing_user][self._editing], id='dlgEdit')) if self._adding_user: users = [ UI.SelectOption(text=x.login, value=x.login) for x in UsersBackend(self.app).get_all_users() if x.uid >= 1000 ] if users: ui.append( 'main', UI.DialogBox(UI.FormLine(UI.Select(*users, name='acct', id='acct'), text='Username'), UI.FormLine(UI.EditPassword( id='passwd', value='Click to add password'), text='Password'), id='dlgAddUser')) else: self.put_message('err', 'No non-root Unix users found') # Config ui.append('tab2', self.get_ui_general()) return ui
def post_install(self, name, path, vars, dbinfo={}): nodectl = apis.langassist(self.app).get_interface('NodeJS') users = UsersBackend(self.app) if not os.path.exists('/usr/bin/python') and os.path.exists('/usr/bin/python'): os.symlink('/usr/bin/python2', '/usr/bin/python') d = json.loads(open(os.path.join(path, 'package.json'), 'r').read()) del d['dependencies']['bcryptjs'] d['dependencies']['bcrypt'] = '0.7.8' open(os.path.join(path, 'package.json'), 'w').write(json.dumps(d)) d = open(os.path.join(path, 'core/server/models/user.js'), 'r').read() d = d.replace('bcryptjs', 'bcrypt') open(os.path.join(path, 'core/server/models/user.js'), 'w').write(d) nodectl.install_from_package(path, 'production') users.add_user('ghost') s = self.app.get_backend(apis.services.IServiceManager) s.edit('ghost', { 'stype': 'program', 'directory': path, 'user': '******', 'command': 'node %s'%os.path.join(path, 'index.js'), 'autostart': 'true', 'autorestart': 'true', 'environment': 'NODE_ENV="production"', 'stdout_logfile': '/var/log/ghost.log', 'stderr_logfile': '/var/log/ghost.log' } ) s.enable('ghost', 'supervisor') addr = vars.getvalue('addr', 'localhost') port = vars.getvalue('port', '80') # Get Mail settings mail_settings = { 'transport' : vars.getvalue('ghost-transport', ''), 'service' : vars.getvalue('ghost-service', ''), 'mail_user' : vars.getvalue('ghost-mail-user', ''), 'mail_pass' : vars.getvalue('ghost-mail-pass', ''), 'from_address' : vars.getvalue('ghost-from-address', '') } # Create/Edit the Ghost config file f = open(os.path.join(path, 'config.example.js'), 'r').read() with open(os.path.join(path, 'config.js'), 'w') as config_file: f = f.replace('http://my-ghost-blog.com', 'http://'+addr+(':'+port if port != '80' else'')) if len(set(mail_settings.values())) != 1 and\ mail_settings['transport'] != '': # If the mail settings exist, add them f = f.replace( "mail: {},",\ 'mail: {\n' "\tfromaddress: '" + mail_settings['from_address'] + "',\n" "\ttransport: '" + mail_settings['transport'] + "',\n" "\t\toptions: {\n" "\t\t\tservice: '" + mail_settings['service'] + "',\n" "\t\t\tauth: {\n" "\t\t\t\tuser: '******'mail_user'] + "',\n" "\t\t\t\tpass: '******'mail_pass'] + "'\n" "\t\t\t}\n" "\t\t}\n" "},\n" ) config_file.write(f) config_file.close() # Finally, make sure that permissions are set so that Ghost # can make adjustments and save plugins when need be. shell('chown -R ghost ' + path)
def post_remove(self, site): users = UsersBackend(self.app) users.del_user('haste') s = self.app.get_backend(apis.services.IServiceManager) s.delete('haste', 'supervisor')
def get_main_ui(self): ui = self.app.inflate('samba:main') ui.find('tabs').set('active', self._tab) # Shares for h in self._cfg.get_shares(): ui.append( 'slist', UI.TblBtn(id='editshare/' + h, icon='gen-folder', name=h, subtext=self._cfg.shares[h]['path'])) if not self._editing_share is None: if self._editing_share == '': ui.append('main', self.get_ui_edit_share()) else: ui.append( 'main', self.get_ui_edit_share( self._cfg.shares[self._editing_share])) # Users for h in sorted(self._cfg.users.keys()): ui.append( 'ulist', UI.TblBtn( id="deluser/" + h, icon="gen-user", name=h, warning= "Are you sure you want to delete %s from the Samba users list?" % h)) #if not self._editing_user is None: # if self._editing_user == '': # ui.append('main', self.get_ui_edit_user()) # else: # if not self._editing_user in self._cfg.users.keys(): # self.put_message('err', 'User not found') # self._editing_user = None # else: # ui.append('main', self.get_ui_edit_user( # self._cfg.users[self._editing_user] # )) if not self._editing is None: ui.append( 'main', UI.InputBox( title=self._editing, value=self._cfg.users[self._editing_user][self._editing], id='dlgEdit')) if self._adding_user: users = [ UI.SelectOption(text=x.login, value=x.login) for x in UsersBackend(self.app).get_all_users() if x.uid >= 1000 ] if users: ui.append( 'main', UI.DialogBox(UI.FormLine(UI.SelectInput(*users, name='acct', id='acct'), text='Username'), UI.Formline(UI.TextInput(id='passwd', name="passwd", password=True, verify="password", verifywith="passwd"), text="Password", feedback="gen-lock", iid="passwd"), UI.Formline(UI.TextInput(id='passwdb', name="passwdb", password=True, verify="password", verifywith="passwd"), text="Confirm password", feedback="gen-lock", iid="passwdb"), id='dlgAddUser', title="Adding user")) else: self.put_message('err', 'No non-root Unix users found') # Config ui.append('tab2', self.get_ui_general()) return ui