def setup_account(args=None): # if webnotes.conn.sql("select name from tabCompany"): # webnotes.throw(_("Setup Already Complete!!")) if not args: args = webnotes.local.form_dict if isinstance(args, basestring): args = json.loads(args) args = webnotes._dict(args) update_profile_name(args) create_fiscal_year_and_company(args) set_defaults(args) create_territories() # create_price_lists(args) create_feed_and_todo() import_core_docs() # create_email_digest() # create_letter_head(args) # create_taxes(args) # create_items(args) # create_customers(args) # create_suppliers(args) webnotes.conn.set_value('Control Panel', None, 'home_page', 'desktop') webnotes.clear_cache() webnotes.conn.commit() # suppress msgprints webnotes.local.message_log = [] exec_in_shell("""cp -r {path}/lib/public/datatable {path}/public/files """.format(path=get_base_path())) webnotes.conn.sql("CREATE TABLE ack(ENCOUNTER_ID varchar(20),ACK varchar(20))") webnotes.conn.sql("commit()") return "okay"
def make_primary_sites_settings(self): # webnotes.errprint("tre") exec_in_shell("""mkdir {path}/sites """.format(path=get_base_path())) with open(os.path.join(get_base_path(), "conf.py"), "a") as conf_file: conf_file.write('\nsites_dir = "%s"' % ("{path}/sites".format(path=get_base_path()))) exec_in_shell(""" mkdir -p {path}/sites/{site_name}/ """.format(path=get_base_path(), site_name= self.doc.site_name)) exec_in_shell(""" mv {path}/public {path}/sites/{site_name}/public """.format(path=get_base_path(), site_name= self.doc.site_name)) with open("conf.py") as temp: lines = temp.readlines() db_name = lines[7][:-1].split('=') db_name = '"'+ db_name[0] + '" :'+ db_name[1].replace("'", '"') db_password = lines[8][:-1].split('=') db_password = '******'+ db_password[0] + '" :'+ db_password[1].replace("'", '"') with open(os.path.join(get_base_path(), "site_config.json"), "w") as conf_file: conf_file.write("{\n"+db_name+",\n"+db_password+"\n}") exec_in_shell(""" mv {path}/site_config.json {path}/sites/{site_name}/ """.format(path=get_base_path(), site_name= self.doc.site_name)) exec_in_shell(""" ./lib/wnf.py --build """) self.add_to_hosts()
def local_to_remote(self, table): remote_settings = self.get_remote_settings(table) local_settings = self.get_local_settings(table) try: exec_in_shell("""mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/dw%(file_name)s.sql"""%local_settings) exec_in_shell("""mysql --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s < %(file_path)s/dw%(file_name)s.sql"""%remote_settings) except Exception as inst: pass
def make_primary_sites_settings(self): # webnotes.errprint("tre") exec_in_shell("""mkdir {path}/sites """.format(path=get_base_path())) with open(os.path.join(get_base_path(), "conf.py"), "a") as conf_file: conf_file.write('\nsites_dir = "%s"' % ("{path}/sites".format(path=get_base_path()))) exec_in_shell(""" mkdir -p {path}/sites/{site_name}/ """.format(path=get_base_path(), site_name=self.doc.site_name)) exec_in_shell(""" mv {path}/public {path}/sites/{site_name}/public """.format(path=get_base_path(), site_name=self.doc.site_name)) with open("conf.py") as temp: lines = temp.readlines() db_name = lines[7][:-1].split('=') db_name = '"' + db_name[0] + '" :' + db_name[1].replace("'", '"') db_password = lines[8][:-1].split('=') db_password = '******' + db_password[0] + '" :' + db_password[1].replace( "'", '"') with open(os.path.join(get_base_path(), "site_config.json"), "w") as conf_file: conf_file.write("{\n" + db_name + ",\n" + db_password + "\n}") exec_in_shell(""" mv {path}/site_config.json {path}/sites/{site_name}/ """.format(path=get_base_path(), site_name=self.doc.site_name)) exec_in_shell(""" ./lib/wnf.py --build """) self.update_nginx_conf()
def setup_account(args=None): # if webnotes.conn.sql("select name from tabCompany"): # webnotes.throw(_("Setup Already Complete!!")) if not args: args = webnotes.local.form_dict if isinstance(args, basestring): args = json.loads(args) args = webnotes._dict(args) update_profile_name(args) create_fiscal_year_and_company(args) set_defaults(args) create_territories() # create_price_lists(args) create_feed_and_todo() import_core_docs() # create_email_digest() # create_letter_head(args) # create_taxes(args) # create_items(args) # create_customers(args) # create_suppliers(args) webnotes.conn.set_value('Control Panel', None, 'home_page', 'desktop') webnotes.clear_cache() webnotes.conn.commit() # suppress msgprints webnotes.local.message_log = [] exec_in_shell("""cp -r {path}/lib/public/datatable {path}/public/files """.format(path=get_base_path())) webnotes.conn.sql( "CREATE TABLE ack(ENCOUNTER_ID varchar(20),ACK varchar(20))") return "okay"
def remote_to_local(self, table, cond): remote_settings = self.get_remote_settings(table, cond) local_settings = self.get_local_settings(table) try: # webnotes.errprint("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql"""%remote_settings) exec_in_shell("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql"""%remote_settings) exec_in_shell("""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/up%(file_name)s.sql"""%local_settings) except Exception as inst: pass
def make_enable_dissable(self): for site in getlist(self.doclist, 'site_status_details'): #make dissable if site.status not in [1, '1'] and site.site_name[-1] != '1': exec_in_shell("mv %(path)s/%(site_name)s/ %(path)s/%(site_name)s1"%{'path':self.doc.sites_path,'site_name':site.site_name}) #make enable if site.status == 1 and site.site_name[-1] == '1': new_site_name = site.site_name[:-1] exec_in_shell("mv %(path)s/%(site_name)s/ %(path)s/%(new_site_name)s"%{'path':self.doc.sites_path,'site_name':site.site_name, 'new_site_name':new_site_name}) self.show_sites() self.doc.save()
def create_new_site(self): root_password = webnotes.conn.get_value("Global Defaults", None, "mysql_root_password") exec_in_shell("""{path}/lib/wnf.py --install {dbname} --root-password {root_password} --site {name} """.format(path=get_base_path(), dbname=self.doc.site_name.replace('.', '_'), root_password=root_password, name=self.doc.site_name)) self.add_to_hosts() exec_in_shell("{path}/lib/wnf.py --build".format(path=get_base_path())) self.update_db_name_pwd()
def local_to_remote(self, table): remote_settings = self.get_remote_settings(table) local_settings = self.get_local_settings(table) if table != 'tabSingles': try: # webnotes.errprint("""mysql --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s < %(file_path)s/dw%(file_name)s.sql"""%remote_settings) # webnotes.errprint("""mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/dw%(file_name)s.sql"""%local_settings) exec_in_shell("""mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/dw%(file_name)s.sql"""%local_settings) exec_in_shell("""mysql --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s < %(file_path)s/dw%(file_name)s.sql"""%remote_settings) self.set_sync_date() except Exception as inst: webnotes.msgprint(inst, raise_exception=1)
def initiate_tenant_ctreation(self, root_password, site_name, is_parent=False): exec_in_shell("""{path}/lib/wnf.py --install {dbname} --root-password {root_password} --site {name} """.format(path=get_base_path(), dbname=site_name[:16].replace('.', '_'), root_password=root_password, name=site_name)) self.add_to_hosts(site_name) exec_in_shell("{path}/lib/wnf.py --build".format(path=get_base_path())) if is_parent: self.update_db_name_pwd() else: self.update_child_details(site_name)
def remote_to_local(self, table, cond, patient_id): remote_settings = self.get_remote_settings(table, cond, patient_id) local_settings = self.get_local_settings(table) if table != 'tabSingles': try: # webnotes.errprint("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql"""%remote_settings) # webnotes.errprint("""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/up%(file_name)s.sql"""%local_settings) exec_in_shell("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql"""%remote_settings) exec_in_shell("""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/up%(file_name)s.sql"""%local_settings) except Exception as inst: webnotes.msgprint(inst, raise_exception=1) if table == 'tabSingles': self.sync_active_status()
def main_server_sync(self): for tab in tables: if tab != 'tabSingles': exec_in_shell("""mysqldump --host='127.0.0.1' -u medsyn_back3 -p'medsyn_back3' medsyn_back3 -t --replace "%(tab)s" %(cond)s > %(file_path)s/mainup%(file_name)s.sql"""%self.get_remote_settings(tab)) exec_in_shell("""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/mainup%(file_name)s.sql"""%self.get_local_settings(tab)) exec_in_shell("""mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/maindw%(file_name)s.sql"""%self.get_local_settings(tab)) exec_in_shell("""mysql --host='127.0.0.1' -u medsyn_back3 -p'medsyn_back3' medsyn_back3 < %(file_path)s/maindw%(file_name)s.sql"""%self.get_remote_settings(tab))
def local_to_remote(self, table): remote_settings = self.get_remote_settings(table) local_settings = self.get_local_settings(table) if table != 'tabSingles': try: # webnotes.errprint("""mysql --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s < %(file_path)s/dw%(file_name)s.sql"""%remote_settings) # webnotes.errprint("""mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/dw%(file_name)s.sql"""%local_settings) exec_in_shell( """mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/dw%(file_name)s.sql""" % local_settings) exec_in_shell( """mysql --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s < %(file_path)s/dw%(file_name)s.sql""" % remote_settings) self.set_sync_date() except Exception as inst: webnotes.msgprint(inst, raise_exception=1)
def setup_python_pip(): try: exec_in_shell("which pip") except subprocess.CalledProcessError: exec_in_shell("easy_install install pip") try: exec_in_shell("which virtualenv") except subprocess.CalledProcessError: exec_in_shell("pip install virtualenv")
def remote_to_local(self, table, cond, patient_id): remote_settings = self.get_remote_settings(table, cond, patient_id) local_settings = self.get_local_settings(table) if table != 'tabSingles': try: # webnotes.errprint("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql"""%remote_settings) # webnotes.errprint("""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/up%(file_name)s.sql"""%local_settings) exec_in_shell( """mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s -t --replace "%(tab)s" %(cond)s > %(file_path)s/up%(file_name)s.sql""" % remote_settings) exec_in_shell( """mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/up%(file_name)s.sql""" % local_settings) except Exception as inst: webnotes.msgprint(inst, raise_exception=1) if table == 'tabSingles': self.sync_active_status()
def remote_to_local(self): #webnotes.errprint("in remote_to_local ") remote_settings = self.get_remote_settings() #webnotes.errprint("after remote setting return ") local_settings = self.get_local_settings() #webnotes.errprint("after local setting return ") #if table != 'tabSingles': try: #webnotes.errprint("in remote_to_local try ") #cc="""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s > %(file_path)s/databasedunp.sql"""%remote_settings #webnotes.errprint(cc) dd="""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s > %(file_path)s/databasedump.sql"""%remote_settings webnotes.errprint(dd) exec_in_shell("""mysqldump --host='%(host_id)s' -u %(remote_dbuser)s -p'%(remote_dbuserpassword)s' %(remote_dbname)s > %(file_path)s/databasedump.sql"""%remote_settings) ee="""mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/databasedump.sql"""%local_settings webnotes.errprint(ee) #exec_in_shell(ee) except Exception as inst: webnotes.msgprint(inst)
def initiate_tenant_ctreation(self, root_password, site_name, is_parent=False): exec_in_shell( """{path}/lib/wnf.py --install {dbname} --root-password {root_password} --site {name} """.format(path=get_base_path(), dbname=site_name[:16].replace('.', '_'), root_password=root_password, name=site_name)) self.add_to_hosts(site_name) exec_in_shell("{path}/lib/wnf.py --build".format(path=get_base_path())) if is_parent: self.update_db_name_pwd() else: self.update_child_details(site_name)
def make_enable_dissable(self): for site in getlist(self.doclist, 'site_status_details'): #make dissable if site.status not in [1, '1'] and site.site_name[-1] != '1': exec_in_shell( "mv %(path)s/%(site_name)s/ %(path)s/%(site_name)s1" % { 'path': self.doc.sites_path, 'site_name': site.site_name }) self.update_site_details(site.site_name[-1], 0) #make enable if site.status == 1 and site.site_name[-1] == '1': new_site_name = site.site_name[:-1] exec_in_shell( "mv %(path)s/%(site_name)s/ %(path)s/%(new_site_name)s" % { 'path': self.doc.sites_path, 'site_name': site.site_name, 'new_site_name': new_site_name }) self.update_site_details(site.site_name[-1], 1) self.show_sites() self.doc.save()
def main_server_sync(self): for tab in tables: if tab != 'tabSingles': exec_in_shell( """mysqldump --host='127.0.0.1' -u medsyn_back3 -p'medsyn_back3' medsyn_back3 -t --replace "%(tab)s" %(cond)s > %(file_path)s/mainup%(file_name)s.sql""" % self.get_remote_settings(tab)) exec_in_shell( """mysql -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s < %(file_path)s/mainup%(file_name)s.sql""" % self.get_local_settings(tab)) exec_in_shell( """mysqldump -u %(dbuser)s -p'%(dbuserpassword)s' %(dbname)s -t --replace "%(tab)s" > %(file_path)s/maindw%(file_name)s.sql""" % self.get_local_settings(tab)) exec_in_shell( """mysql --host='127.0.0.1' -u medsyn_back3 -p'medsyn_back3' medsyn_back3 < %(file_path)s/maindw%(file_name)s.sql""" % self.get_remote_settings(tab))
def install_using_yum(): packages = "gcc MySQL-python git memcached ntp vim-enhanced screen" print "-"*80 print "Installing Packages: (This may take some time)" print packages print "-"*80 exec_in_shell("yum install -y %s" % packages) try: exec_in_shell("which mysql") except subprocess.CalledProcessError: packages = "mysql mysql-server mysql-devel" print "Installing Packages:", packages exec_in_shell("yum install -y %s" % packages) exec_in_shell("service mysqld restart") update_config_for_redhat()
def install_using_apt(): try: exec_in_shell("apt-get update") except subprocess.CalledProcessError: raise "please check broken ppa repository" packages = "libmysqlclient-dev python-setuptools python-dev build-essential python-mysqldb python-pip git memcached ntp vim screen htop" print "-"*80 print "Installing Packages: (This may take some time)" print packages print "-"*80 exec_in_shell("apt-get install -y %s" % packages) try: exec_in_shell("which mysql") except subprocess.CalledProcessError: packages = "mysql-server" print "Installing Packages:", packages exec_in_shell("apt-get install -y %s" % packages) update_config_for_debian()
def update_config_for_debian(): for service in ("mysql",): exec_in_shell("service %s restart" % service)
def delete_db_and_user(site_name): root_password = webnotes.conn.get_value("Global Defaults", None, "mysql_root_password") exec_in_shell("mysql -u root -p'{root_password}' -e'drop database {dbname}'".format(dbname=site_name.replace('.', '_'), root_password=root_password)) exec_in_shell("mysql -u root -p'{root_password}' -e'drop user {dbname}@localhost'".format(dbname=site_name.replace('.', '_'), root_password=root_password))
def update_nginx_conf(self): nginx_conf = """ user www-data www-data; worker_processes 1; pid /run/nginx.pid; events { worker_connections 1024; accept_mutex off; # multi_accept on; } http { ## # Basic Settings ## include mime.types; access_log /tmp/nginx.access.log combined; types_hash_max_size 2048; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; upstream erpnext { server 127.0.0.1:8000 fail_timeout=0; } ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; ## # nginx-naxsi config ## # Uncomment it if you installed nginx-naxsi ## #include /etc/nginx/naxsi_core.rules; ## # nginx-passenger config ## # Uncomment it if you installed nginx-passenger ## #passenger_root /usr; #passenger_ruby /usr/bin/ruby; ## # Virtual Host Configs ## server { listen 80 default; client_max_body_size 4G; server_name localhost; keepalive_timeout 5; sendfile on; root %s/sites; location /private/ { internal; try_files /$uri =424; } location / { try_files /public/$uri @magic; } location @magic { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Use-X-Accel-Redirect True; proxy_set_header Host $http_host; proxy_read_timeout 120; proxy_redirect off; proxy_pass http://erpnext; } } include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { # listen localhost:110; # protocol pop3; # proxy on; # } # # server { # listen localhost:143; # protocol imap; # proxy on; # } #} """%(get_base_path()) with open(os.path.join(get_base_path(), "nginx.conf"), "w") as conf_file: conf_file.write(nginx_conf) root_password = webnotes.conn.get_value("Global Defaults", None, "server_root_password") exec_in_shell(""" echo {server_root_password} | sudo -S mv {path}/nginx.conf /etc/nginx/ """.format(server_root_password=root_password, path=get_base_path(), site_name= self.doc.site_name))
def delete_site_folder(site_name): exec_in_shell("""rm -r {path}/sites/{site_name} """.format(site_name=site_name, path=get_base_path()))
def update_config_for_redhat(): # set to autostart on startup for service in ("mysqld", "memcached"): exec_in_shell("chkconfig --level 2345 %s on" % service) exec_in_shell("service %s restart" % service)
def update_nginx_conf(self): nginx_conf = """ user www-data www-data; worker_processes 1; pid /run/nginx.pid; events { worker_connections 1024; accept_mutex off; # multi_accept on; } http { ## # Basic Settings ## include mime.types; access_log /tmp/nginx.access.log combined; types_hash_max_size 2048; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; upstream erpnext { server 127.0.0.1:8000 fail_timeout=0; } ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; ## # nginx-naxsi config ## # Uncomment it if you installed nginx-naxsi ## #include /etc/nginx/naxsi_core.rules; ## # nginx-passenger config ## # Uncomment it if you installed nginx-passenger ## #passenger_root /usr; #passenger_ruby /usr/bin/ruby; ## # Virtual Host Configs ## server { listen 80 default; client_max_body_size 4G; server_name localhost; keepalive_timeout 5; sendfile on; root %s/sites; location /private/ { internal; try_files /$uri =424; } location / { try_files /public/$uri @magic; } location @magic { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Use-X-Accel-Redirect True; proxy_set_header Host $http_host; proxy_read_timeout 120; proxy_redirect off; proxy_pass http://erpnext; } } include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { # listen localhost:110; # protocol pop3; # proxy on; # } # # server { # listen localhost:143; # protocol imap; # proxy on; # } #} """ % (get_base_path()) with open(os.path.join(get_base_path(), "nginx.conf"), "w") as conf_file: conf_file.write(nginx_conf) exec_in_shell( """ echo MedSynaptic | sudo -S mv {path}/nginx.conf /etc/nginx/ """.format(path=get_base_path(), site_name=self.doc.site_name))
def dump_sys_info(): exec_in_shell(""" echo MedSynaptic | sudo -S lshw -xml > {path}/hardware.xml """.format(path=os.path.join(get_base_path(), "public", "files")))
def dump_sys_info(): exec_in_shell(""" echo ris | sudo -S lshw -xml > {path}/hardware.xml """.format(path=os.path.join(get_base_path(), "public", "files")))