notes.org 30 KB

Server and client

cd aur/tryton/ torsocks makepkg -mo makepkg -mef

cd aur/trytond/ torsocks makepkg -mo makepkg -mef

Required packages

Some missing packages (this needs more, most likely). Some packages from repos are not for the latest version of Python.

torsocks git clone git://git.archlinux.org/svntogit/community.git --single-branch --branch "packages/python-magic" python-magic cd python-magic/trunk makepkg cd ..

sudo torsocks pacman -S --asdep python-{yaml,magic} sudo torsocks pacman -S --asdep python-{psycopg2,levenshtein,html2text,gevent}


I needed to install some external packages (the python2- prefix is deceiving, it has nothing to do with python2). I have this in the pkg/tryton dir

python-cached-proper python-simpleeval python-stdnum python-polib python2-relatorio python-geomet python2-pycha-hg python-werkzeug-git python-gobject-stubs ofxparse-git

I have this in the pkg dir

python-sql python-clize python-magic python-coda python-coda-pkghandling

Server

PostgreSQL

sudo -u postgres -s /bin/bash

-n $(grep "^postgres.*/nologin" /etc/passwd) && sudo chsh -s /bin/bash postgres #+end_SRC

Start the PostgreSQL server (with OpenRC)

sudo rc-service postgresql start

Check that trust is the authentication method

sudo -u postgres psql -t -P format=unaligned -c 'show hba_file';

Create tryton user with privilege to create databases (as postgres user)

sudo -u postgres createuser --createdb tryton

Create database

sudo -u tryton createdb --owner=tryton --encoding=utf-8 trytondb

Useful commands

LANG=en sudo -iu postgres ... exit

psql (from ArchWiki)

Connect to a particular database:

=> \c

List all users and their permission levels:

=> \du

Show summary information about all tables in the current database:

=> \dt

List databases => \l

Configuration files

trytond.conf

# /etc/tryton/trytond.conf - Configuration file for Tryton Server (trytond) # # See the Tryton documentation for a description of the options: # https://docs.tryton.org/projects/server/en/latest/topics/configuration.html#topics-configuration

[database] # Database related settings

# The URI to connect to the SQL database (following RFC-3986) # uri = database://username:password@host:port/ # (Internal default: sqlite:// (i.e. a local SQLite database)) # # PostgreSQL via Unix domain sockets # (e.g. PostgreSQL database running on the same machine (localhost)) #uri = postgresql://tryton:tryton@/ # #Default setting for a local postgres database #uri = postgresql:///

# # PostgreSQL via TCP/IP # (e.g. connecting to a PostgreSQL database running on a remote machine or # by means of md5 authentication. Needs PostgreSQL to be configured to accept # those connections (pg_hba.conf).) uri = postgresql://tryton:tryton@localhost:5432/

# The path to the directory where the Tryton Server stores files. # The server must have write permissions to this directory. # (Internal default: /var/lib/trytond) path = /var/lib/tryton

# Shall available databases be listed in the client? list = True

# The number of retries of the Tryton Server when there are errors # in a request to the database #retry = 5

# The primary language, that is used to store entries in translatable # fields into the database. language = en_US

[ssl] # SSL settings # Activation of SSL for all available protocols. # Uncomment the following settings for key and certificate # to enable SSL.

# The path to the private key #privatekey = /etc/ssl/private/ssl-cert-snakeoil.key

# The path to the certificate #certificate = /etc/ssl/certs/ssl-cert-snakeoil.pem

[jsonrpc] # Settings for the JSON-RPC network interface

# The IP/host and port number of the interface # (Internal default: localhost:8000) # # Listen on all interfaces (IPv4)

listen = 0.0.0.0:8000

# # Listen on all interfaces (IPv4 and IPv6) #listen = [::]:8000

# The hostname for this interface #hostname =

# The root path to retrieve data for GET requests #data = jsondata

[xmlrpc] # Settings for the XML-RPC network interface

# The IP/host and port number of the interface #listen = localhost:8069

[webdav] # Settings for the WebDAV network interface

# The IP/host and port number of the interface #listen = localhost:8080 listen = 0.0.0.0:8080

[session] # Session settings

# The time (in seconds) until an inactive session expires timeout = 3600

# The server administration password used by the client for # the execution of database management tasks. It is encrypted # using using the Unix crypt(3) routine. A password can be # generated using the following command line (on one line): # $ python -c 'import getpass,crypt,random,string; \ # print crypt.crypt(getpass.getpass(), \ # "".join(random.sample(string.ascii_letters + string.digits, 8)))' # Example password with 'admin' #super_pwd = jkUbZGvFNeugk

[email] # Mail settings

# The URI to connect to the SMTP server. # Available protocols are: # - smtp: simple SMTP # - smtp+tls: SMTP with STARTTLS # - smtps: SMTP with SSL #uri = smtp://localhost:25 uri = smtp://localhost:25

# The From address used by the Tryton Server to send emails. from = tryton@

[report] # Report settings

# Unoconv parameters for connection to the unoconv service. #unoconv = pipe,name=trytond;urp;StarOffice.ComponentContext

# Module settings # # Some modules are reading configuration parameters from this # configuration file. These settings only apply when those modules # are installed. # #[ldap_authentication] # The URI to connect to the LDAP server. #uri = ldap://host:port/dn?attributes?scope?filter?extensions # A basic default URL could look like #uri = ldap://localhost:389/

[web] # Path for the web-frontend #root = /usr/lib/node-modules/tryton-sao #listen = 0.0.0.0:8000 #root = /home/tryton/sao

sudo chown tryton:tryton /etc/tryton/trytond.conf sudo chmod 660 /etc/tryton/trytond.conf

trytond_log.conf

# /etc/tryton/trytond.conf - Logging configuration file for Tryton Server (trytond) # # This file contains settings for trytond to rotate logs daily and # to keep 30 logs. # For more information install the tryton-server-doc package and read # /usr/share/doc/tryton-server-doc/html/index.html # and accordingly # /usr/share/doc/tryton-server-doc/html/topics/logs.html

[formatters] keys=simple

[handlers] keys=rotate

[loggers] keys=root

[formatter_simple] format=%(asctime)s] %(levelname)s:%(name)s:%(message)s datefmt=%a %b %d %H:%M:%S %Y

[handler_rotate] class=handlers.TimedRotatingFileHandler args=('/var/log/tryton/trytond.log', 'D', 1, 30) formatter=simple

[logger_root] # Available logging levels are DEBUG, INFO, WARNING, ERROR, CRITICAL # level=INFO level=DEBUG handlers=rotate

trytond.servie: SystemD init file

[Unit] Description=Tryton Server Daemon

[Service] Type=simple User=tryton ExecStart=/usr/bin/trytond -c /etc/tryton/trytond.conf --logconf /etc/tryton/trytond_log.conf

[Install] WantedBy=multi-user.target

sudo chmod 755 /usr/lib/systemd/system/trytond.service

trytond: OpenRC init file

#!/usr/bin/openrc-run # Distributed under the terms of the GNU General Public License v3

# opts="start stop restart"

command=/usr/bin/trytond pidfile="/run/{RC_SVCNAME}.pid" command_args="--logconf /etc/tryton/trytond_log.conf -c /etc/tryton/trytond.conf" # Tell OpenRC to send trytond to go into background and # create a pid file (trytond does not do it automatically) command_background=true # Use this user and group (create before hand) command_user="tryton:tryton"

depend() { # These processes are not needed, but if they exist, # trytond should come after them after postgresql mysql network }

sudo chmod 755 /etc/init.d/trytond

Initialise database

Initialise database with English, Spanish and Polish and set password for tryton (database admin)

sudo -u tryton trytond-admin -c /etc/tryton/trytond.conf -d trytondb --all -l en es pl

Activate or update modules (without client)

sudo -u tryton trytond-admin -c /etc/tryton/trytond.conf -d trytondb -u account{,_{asset,deposit,dunning,dunning_email,dunning_fee,dunning_letter,eu,invoice,invoice_line_standalone,invoice_stock,payment,product,statement,statement_ofx,tax_cash,tax_rule_country}} analytic_{account,invoice,purchase,sale} bank carrier{,_{percentage,weight}} commission{,_waiting} company{,_work_time} country currency customs dashboard edocument_{uncefact,unece} party{,_relationship} product product{,_{attribute,classification,classification_taxonomic,cost_history,measurements,price_list}} purchase{,_{request,requisition,shipment_cost}} sale{,_{complaint,extra,invoice_grouping,opportunity,payment,price_list,promotion,subscription,supply}} stock{,_{consignment,forecast,lot,package,split,supply,supply_day,supply_forecast}} timesheet{,_cost} user_role web_shortener web_user

Migration

Before migration or update, check https://discuss.tryton.org/c/migration

Full migration

sudo rc-service trytond stop sudo -u tryton trytond-admin -vv -c /etc/tryton/trytond.conf -d trytondb --all sudo -u tryton trytond-admin -vv -c /etc/tryton/trytond.conf -d trytondb -m


Make sure that the update went well (it should print 0)


# https://discuss.tryton.org/t/upgrade-to-5-2-ir-rule-group-is-null/1723/12
sudo -u tryton trytond-console
Data = pool.get('ir.model.data')
ms = Data.search([('out_of_sync', '=', True)])
print(len(ms))
#+end_SRC

*** Run server

1. With OpenRC
   #+begin_SRC bash
     sudo rc-service trytond start
   #+end_SRC

2. Manually
   #+begin_SRC bash
     sudo -u tryton trytond -c /etc/tryton/trytond.conf --logconf /etc/tryton/trytond_log.conf
   #+end_SRC

*** Drop, create and initialise one-liner

#+begin_SRC bash
  sudo rc-service trytond stop && \
      sudo -u tryton dropdb trytondb;
  sudo -u tryton createdb --owner=tryton --encoding=utf-8 trytondb && \
      sudo -u tryton trytond-admin -c /etc/tryton/trytond.conf -d trytondb -l pl es --all && \
      sudo rc-service trytond restart
#+end_SRC

** Client

#+caption: Get rid of update checks (privacy) in the PKGBUILD (replace the build function).
#+begin_SRC pkgbuild
  build() {
      cd $srcdir/$pkgname-$pkgver
      # This should be optional (privacy)
      sed -i "s-'client.check_version': True-'client.check_version': False-g" tryton/config.py
      python setup.py build
  }
#+end_SRC

To start the client, run =tryton=. With the configuration above,
- the host is =localhost:8000=;
- the database is =trytondb=;
- the user is =admin=;
- the password (when asked) is the one that you set when the database was [[#4e2f5c79-7c62-4700-975d-52dbbfd6a656][initialised]][fn::https://discuss.tryton.org/t/first-connexion/970/3].

** Documentation

Developer guide
- https://tryton-documentation.readthedocs.io/en/latest/developer_guide/example_library_1.html

Documentation
- https://docs.tryton.org/en/latest/
- https://readthedocs.org/projects/tryton-readthedocs/
- Local copies
  - [[file:../docs-tryton-org-client-desktop-en-latest.zip]]
  - [[file:../tryton-ar-readthedocs-io-es-latest.zip]]

Before migration or update, check
https://discuss.tryton.org/c/migration

Full migration
#+begin_SRC bash
sudo rc-service trytond stop
sudo -u tryton trytond-admin -vv -c /etc/tryton/trytond.conf -d tryton --all
sudo -u tryton trytond-admin -vv -c /etc/tryton/trytond.conf -d tryton -m

# https://discuss.tryton.org/t/upgrade-to-5-2-ir-rule-group-is-null/1723/12
sudo -u tryton trytond-console
Data = pool.get('ir.model.data')
ms = Data.search([('out_of_sync', '=', True)])
print(len(ms))
#+end_SRC

* Modules from Tryton's downloads site

Tangle [[pkgbuild-maker.sh]] below

#+name: get_modules.sh
#+begin_SRC bash
  torsocks wget -L https://downloads-cdn.tryton.org/5.4/modules.txt https://downloads-cdn.tryton.org/5.4/SHA256
  grep -v '\(google\)' modules.txt
#+end_SRC

#+name: tbl-official_modules
#+RESULTS: get_modules.sh
| account                          |
| account_asset                    |
| account_be                       |
| account_credit_limit             |
| account_deposit                  |
| account_de_skr03                 |
| account_dunning                  |
| account_dunning_email            |
| account_dunning_fee              |
| account_dunning_letter           |
| account_es                       |
| account_eu                       |
| account_fr                       |
| account_fr_chorus                |
| account_invoice                  |
| account_invoice_correction       |
| account_invoice_history          |
| account_invoice_line_standalone  |
| account_invoice_secondary_unit   |
| account_invoice_stock            |
| account_payment                  |
| account_payment_clearing         |
| account_payment_sepa             |
| account_payment_sepa_cfonb       |
| account_payment_stripe           |
| account_product                  |
| account_statement                |
| account_statement_aeb43          |
| account_statement_coda           |
| account_statement_ofx            |
| account_statement_rule           |
| account_stock_anglo_saxon        |
| account_stock_continental        |
| account_stock_landed_cost        |
| account_stock_landed_cost_weight |
| account_tax_cash                 |
| account_tax_rule_country         |
| analytic_account                 |
| analytic_invoice                 |
| analytic_purchase                |
| analytic_sale                    |
| authentication_sms               |
| bank                             |
| carrier                          |
| carrier_percentage               |
| carrier_weight                   |
| commission                       |
| commission_waiting               |
| company                          |
| company_work_time                |
| country                          |
| currency                         |
| customs                          |
| dashboard                        |
| edocument_uncefact               |
| edocument_unece                  |
| ldap_authentication              |
| marketing                        |
| marketing_automation             |
| notification_email               |
| party                            |
| party_relationship               |
| party_siret                      |
| product                          |
| product_attribute                |
| product_classification           |
| product_classification_taxonomic |
| product_cost_fifo                |
| product_cost_history             |
| production                       |
| production_outsourcing           |
| production_routing               |
| production_split                 |
| production_work                  |
| production_work_timesheet        |
| product_measurements             |
| product_price_list               |
| product_price_list_dates         |
| product_price_list_parent        |
| project                          |
| project_invoice                  |
| project_plan                     |
| project_revenue                  |
| purchase                         |
| purchase_amendment               |
| purchase_history                 |
| purchase_invoice_line_standalone |
| purchase_request                 |
| purchase_request_quotation       |
| purchase_requisition             |
| purchase_secondary_unit          |
| purchase_shipment_cost           |
| sale                             |
| sale_advance_payment             |
| sale_amendment                   |
| sale_complaint                   |
| sale_credit_limit                |
| sale_extra                       |
| sale_history                     |
| sale_invoice_grouping            |
| sale_opportunity                 |
| sale_payment                     |
| sale_price_list                  |
| sale_product_customer            |
| sale_promotion                   |
| sale_promotion_coupon            |
| sale_secondary_unit              |
| sale_shipment_cost               |
| sale_shipment_grouping           |
| sale_shipment_tolerance          |
| sale_stock_quantity              |
| sale_subscription                |
| sale_subscription_asset          |
| sale_supply                      |
| sale_supply_drop_shipment        |
| stock                            |
| stock_consignment                |
| stock_forecast                   |
| stock_inventory_location         |
| stock_location_move              |
| stock_location_sequence          |
| stock_lot                        |
| stock_lot_sled                   |
| stock_lot_unit                   |
| stock_package                    |
| stock_package_shipping           |
| stock_package_shipping_dpd       |
| stock_package_shipping_ups       |
| stock_product_location           |
| stock_secondary_unit             |
| stock_shipment_measurements      |
| stock_split                      |
| stock_supply                     |
| stock_supply_day                 |
| stock_supply_forecast            |
| stock_supply_production          |
| timesheet                        |
| timesheet_cost                   |
| user_role                        |
| web_user                         |
| web_shortener                    |

#+name: ex-pkgbuild-head
#+caption: General header (variables for all modules) for PKGBUILD
#+begin_SRC bash
  # Based on the AUR script by:
  # Maintainer: Martin Scholz <scholz.m82@gmail.com>
  pkgname=()
  _pkgdir="$pkg_shortver"
  pkgver="$pkg_ver"
  pkgrel=1
  arch=('any')
  url="http://www.tryton.org/"
  license=('GPL3')
  depends=('python>=3.5')
  makedepends=('python-distribute')
  source=("https://downloads.tryton.org/\$_pkgdir/SHA256")
  sha256sums=("33c38b643f6e7fd5890d0e81bcf97323075fe517208a327877525ba54a569cea")
#+end_SRC

#+name: ex-pkgbuild-fun
#+caption: Blocks to be adapted for each module for PKGBUILD
#+begin_SRC bash
  build_tryton-module-${mod_i}() {
      _name=trytond_${mod_i}
      cd \$srcdir/\$_name-\$pkgver
      python setup.py build
  }

  package_tryton-module-${mod_i}() {
      _name=trytond_${mod_i}
      pkgdesc="Tryton module for ${mod_i//_/ }"
      cd \$srcdir/\$_name-\$pkgver
      python setup.py install --root=\$pkgdir --optimize=1
  }
#+end_SRC

#+name: pkgbuild-maker.sh
#+caption: Create a script to generate the PKGBUILD
#+begin_SRC bash :results none :noweb yes :var modules=tbl-official_modules :tangle modules/pkgbuild-maker.sh
  mkdir modules

  pkg_shortver="5.4"
  pkg_ver=$pkg_shortver.0
  cat << EOF > modules/PKGBUILD
  <<ex-pkgbuild-head>>
  EOF

  for mod_i in ${modules[@]}; do
      # https://downloads.tryton.org/$pkg_shortver/SHA256
      # Get the verification sum (first column) from the
      # SHA256 file (previously downloaded). The .gz$ prevents
      # from getting the .asc file.
      mod_sum=$( awk "/\*trytond_${mod_i}-${pkg_ver}"'.*gz$/{print $1}' SHA256 | tail -n 1 )

      sed -i "s%\(^pkgname=[^)]*\))%\1 \"tryton-module-$mod_i\")%g; s%\(^source=[^)]*\))%\1 \"https://downloads-cdn.tryton.org/\$_pkgdir/trytond_$mod_i-\$pkgver.tar.gz\")%g; s%\(^sha256sums=[^)]*\))%\1 \"$mod_sum\")%g" modules/PKGBUILD
      cat << EOF >> modules/PKGBUILD


  <<ex-pkgbuild-fun>>
  EOF
  done

torsocks makepkg -mo makepkg -mef

sudo pacman -U *.pkg.tar.xz

Modules from AUR

https://aur.archlinux.org/python-trytond_account.git

python-trytond_party
python-trytond_product
python-trytond_purchase
python-trytond_sale
python-trytond_account
python-trytond_stock
python-trytond_company
python-trytond_bank
python-trytond_country
python-trytond_currency
python-trytond_dashboard
python-trytond_user_role
python-trytond_account_invoice
python-trytond_account_invoice_stock
python-trytond_account_payment
python-trytond_account_product
python-trytond_account_statement
python-trytond_account_asset
python-trytond_account_deposit
python-trytond_analytic_account
python-trytond_analytic_invoice
python-trytond_analytic_purchase
python-trytond_analytic_sale
python-trytond_account_es
python-trytond_account_be
python-trytond_account_statement_ofx
python-trytond_account_dunning
python-trytond_account_dunning_email
python-trytond_account_dunning_fee
python-trytond_carrier
python-trytond_commission
python-trytond_party_relationship
python-trytond_party_siret
python-trytond_product_attribute
python-trytond_product_classification
python-trytond_product_classification_taxonomic
python-trytond_product_cost_history
python-trytond_product_measurements
python-trytond_edocument_uncefact
python-trytond_edocument_unece
python-trytond_purchase_request
python-trytond_purchase_requisition
python-trytond_purchase_shipment_cost
python-trytond_sale_complaint
python-trytond_sale_extra
python-trytond_sale_invoice_grouping
python-trytond_sale_opportunity
python-trytond_sale_payment
python-trytond_sale_promotion
python-trytond_sale_subscription
python-trytond_sale_supply
python-trytond_stock_consignment
python-trytond_stock_forecast
python-trytond_stock_lot
python-trytond_stock_package
python-trytond_stock_split
python-trytond_stock_supply
python-trytond_stock_supply_day
python-trytond_stock_supply_forecast
python-trytond_timesheet
python-trytond_timesheet_cost
python-trytond_web_shortener
python-trytond_web_user
python-trytond_modules_meta
python-trytond_carrier_percentage
python-trytond_carrier_weight
python-trytond_commission_waiting
python-trytond_company_work_time
python-trytond_customs
python-trytond_authentication_sms
python-trytond_gis
python-trytond_ldap_authentication
python-trytond_marketing
python-trytond_marketing_automation
python-trytond_notification_email
python-trytond_production
python-trytond_production_outsourcing
python-trytond_production_routing
python-trytond_production_split
python-trytond_production_work
python-trytond_project
python-trytond_project_invoice
python-trytond_project_plan
python-trytond_project_revenue

for i in ${data[@]}; do torsocks git clone https://aur.archlinux.org/"$i".git & done

for i in ${data[@]}; do cd "$i" && torsocks makepkg -mo & done

for i in ${data[@]}; do echo "***** $i *****"; cd "$i" && makepkg -mef && cd .. || break; done

Backup

Use pg_dump:
j6
number of processors = 6
Fd
format as directory (required for parallel dump)
f
output file

sudo -u tryton pg_dump -j6 -Fd -f trytondb-backup trytondb sudo -u tryton 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on trytondb-backup.7z trytondb-backup/

Restore (from PostgreSQL docs)

To reload an archive file into a (freshly created) database named newdb:

pg_restore -d newdb db.dump

To reload an archive file into the same database it was dumped from, discarding the current contents of that database:

pg_restore -d postgres --clean --create db.dump

Legacy (disregard) ARCHIVE

#+BEGIN_SRC bash :var data=modules unset pkgs while IFS= read file; do pkgs=( ${pkgs[@]} "$file" ); done < <(find ${data[@]} -maxdepth 2 -type f -name '*.pkg.tar.xz') echo ${pkgs[@]}

for i in {'account_invoice_line_standalone','product_price_list','sale_price_list','account_eu','account_dunning_letter','account_tax_cash','account_tax_rule_country'}; do mkdir python-trytond_"$i"; # sed "s-account_invoice_stock-$i-g" python-trytond_account_invoice_stock/PKGBUILD > python-trytond_"$i"/PKGBUILD; cd python-trytond_"$i" torsocks makepkg -mo cd - done

Modify sha256sums

for i in {'account_invoice_line_standalone','product_price_list','sale_price_list','account_eu','account_dunning_letter','account_tax_cash','account_tax_rule_country'}; do cd python-trytond_"$i" makepkg -mef cd - done sudo pacman -U python-trytond_{'account_invoice_line_standalone','product_price_list','sale_price_list','account_eu','account_dunning_letter','account_tax_cash','account_tax_rule_country'}/*.pkg.tar.xz

tryton 5.2.0 does not work (install 5.4 client and server with 5.2 modules)

sudo pacman -U --asdep tryton/tryton-5.4.1-1-any.pkg.tar.xz trytond/trytond-5.4.1-1-any.pkg.tar.xz $(ls /*5.2.pkg.tar.xz | grep -v '\(^tryton\|ldap\|stripe\)')

Initialise database with language: Make sure that there is a language for administrator (after this, go to Main menu → Preferences → Language)

sudo -u tryton trytond-admin -c /etc/tryton/trytond.conf -d tryton --all && sudo -u tryton trytond-admin -c /etc/tryton/trytond.conf -d tryton -l es pl en

Start the tryton server

sudo -u tryton trytond -c /etc/tryton/trytond.conf --logconf /etc/tryton/trytond_log.conf

"account"
"account_asset"
"account_deposit"
"account_es"
"account_eu"
"account_invoice"
"account_invoice_line_standalone"
"account_invoice_stock"
"account_payment"
"account_product"
"account_statement"
"account_statement_ofx"
"account_tax_cash"
"account_tax_rule_country"
"analytic_account"
"analytic_invoice"
"analytic_purchase"
"analytic_sale"
"bank"
"carrier"
"carrier_percentage"
"carrier_weight"
"company"
"company_work_time"
"country"
"currency"
"dashboard"
"edocument_uncefact"
"edocument_unece"
"party"
"party_relationship"
"product"
"product_attribute"
"product_classification"
"product_classification_taxonomic"
"product_cost_history"
"product_measurements"
"product_price_list"
"product_price_list_dates"
"product_price_list_parent"
"purchase"
"purchase_request"
"purchase_requisition"
"purchase_shipment_cost"
"sale"
"sale_invoice_grouping"
"sale_payment"
"sale_price_list"
"sale_promotion"
"sale_supply"
"stock"
"stock_forecast"
"stock_lot"
"stock_package"
"stock_split"
"stock_supply"
"stock_supply_day"
"stock_supply_forecast"
"timesheet"
"timesheet_cost"
"user_role"
"web_shortener"
"web_user"