libreqda 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. CHANGELOG.md +481 -0
  2. libreqda-1.2.0.dist-info/LICENSE.txt +28 -0
  3. libreqda-1.2.0.dist-info/METADATA +131 -0
  4. libreqda-1.2.0.dist-info/RECORD +255 -0
  5. libreqda-1.2.0.dist-info/WHEEL +4 -0
  6. libreqda-1.2.0.dist-info/entry_points.txt +4 -0
  7. scripts/babelrc +8 -0
  8. scripts/dist/LICENSE.txt +33 -0
  9. scripts/dist/RELEASE.txt +23 -0
  10. scripts/dist/macos/libreqda.icns +0 -0
  11. scripts/dist/macos/macos.spec +43 -0
  12. scripts/dist/macos/plist.patch +10 -0
  13. scripts/dist/macos/taguette.icns +0 -0
  14. scripts/dist/macos/taguette_console_wrapper +4 -0
  15. scripts/dist/macos.sh +32 -0
  16. scripts/dist/pyinstaller_entrypoint.py +19 -0
  17. scripts/dist/windows/windows-installer.iss +51 -0
  18. scripts/dist/windows/windows.spec +39 -0
  19. scripts/edugain/worker_update_edugain_idps.py +89 -0
  20. scripts/edugain/worker_update_edugain_idps.sh +9 -0
  21. scripts/make_password_reset_link.py +56 -0
  22. scripts/make_theme.py +99 -0
  23. scripts/new_db_revision.sh +8 -0
  24. scripts/register_user.py +76 -0
  25. scripts/update_pot.sh +33 -0
  26. scripts/update_translations.sh +17 -0
  27. scripts/validate.py +140 -0
  28. scripts/wipe_and_disable_user.py +90 -0
  29. taguette/__init__.py +13 -0
  30. taguette/access_control.py +145 -0
  31. taguette/convert.py +623 -0
  32. taguette/database/__init__.py +177 -0
  33. taguette/database/base.py +9 -0
  34. taguette/database/copy.py +433 -0
  35. taguette/database/models.py +920 -0
  36. taguette/demodata.py +688 -0
  37. taguette/export.py +500 -0
  38. taguette/extract.py +287 -0
  39. taguette/import_codebook.py +110 -0
  40. taguette/l10n/de_DE/LC_MESSAGES/taguette_javascript.mo +0 -0
  41. taguette/l10n/de_DE/LC_MESSAGES/taguette_main.mo +0 -0
  42. taguette/l10n/el_EL/LC_MESSAGES/taguette_javascript.mo +0 -0
  43. taguette/l10n/el_GR/LC_MESSAGES/taguette_javascript.mo +0 -0
  44. taguette/l10n/el_GR/LC_MESSAGES/taguette_main.mo +0 -0
  45. taguette/l10n/en_US/LC_MESSAGES/taguette_javascript.mo +0 -0
  46. taguette/l10n/en_US/LC_MESSAGES/taguette_main.mo +0 -0
  47. taguette/l10n/es_ES/LC_MESSAGES/taguette_javascript.mo +0 -0
  48. taguette/l10n/es_ES/LC_MESSAGES/taguette_main.mo +0 -0
  49. taguette/l10n/fr_FR/LC_MESSAGES/taguette_javascript.mo +0 -0
  50. taguette/l10n/fr_FR/LC_MESSAGES/taguette_main.mo +0 -0
  51. taguette/l10n/id_ID/LC_MESSAGES/taguette_javascript.mo +0 -0
  52. taguette/l10n/id_ID/LC_MESSAGES/taguette_main.mo +0 -0
  53. taguette/l10n/it_IT/LC_MESSAGES/taguette_javascript.mo +0 -0
  54. taguette/l10n/it_IT/LC_MESSAGES/taguette_main.mo +0 -0
  55. taguette/l10n/nl_NL/LC_MESSAGES/taguette_javascript.mo +0 -0
  56. taguette/l10n/nl_NL/LC_MESSAGES/taguette_main.mo +0 -0
  57. taguette/l10n/pt_PT/LC_MESSAGES/taguette_javascript.mo +0 -0
  58. taguette/l10n/pt_PT/LC_MESSAGES/taguette_main.mo +0 -0
  59. taguette/l10n/sv_SE/LC_MESSAGES/taguette_javascript.mo +0 -0
  60. taguette/l10n/sv_SE/LC_MESSAGES/taguette_main.mo +0 -0
  61. taguette/loki_handler.py +107 -0
  62. taguette/main.py +649 -0
  63. taguette/migrations/env.py +72 -0
  64. taguette/migrations/script.py.mako +24 -0
  65. taguette/migrations/versions/09c662cd9483_make_documents_filename_not_null.py +39 -0
  66. taguette/migrations/versions/1b29e68900c1_add_user_roles.py +55 -0
  67. taguette/migrations/versions/1b96a606551d_update_user_to_have_a_display_name.py +34 -0
  68. taguette/migrations/versions/2467bab602b7_add_color_column_to_tags_table.py +33 -0
  69. taguette/migrations/versions/382db36f20f4_add_user_disabled.py +66 -0
  70. taguette/migrations/versions/43d6c240309d_remove_document_groups.py +81 -0
  71. taguette/migrations/versions/447d636f72c5_cascades.py +40 -0
  72. taguette/migrations/versions/491de2dc7cd7_add_indexes.py +51 -0
  73. taguette/migrations/versions/4c55b3b3ff30_user_login_length.py +58 -0
  74. taguette/migrations/versions/61a4abcc8769_user_with_parent_for_permissions.py +40 -0
  75. taguette/migrations/versions/6489b5f9cfb5_increase_password_hash_size.py +34 -0
  76. taguette/migrations/versions/679f625e6e6a_fix_unique_tags.py +59 -0
  77. taguette/migrations/versions/77c4543a5b9b_add_parent_id_column_to_collection_table.py +41 -0
  78. taguette/migrations/versions/7c94b7a31e69_add_is_archived_column_to_projets.py +39 -0
  79. taguette/migrations/versions/7f56de97e3c8_change_edugain_displayname_length.py +42 -0
  80. taguette/migrations/versions/807c0cc0ecf6_remove_invalid_hltags.py +43 -0
  81. taguette/migrations/versions/80b1cc9d4c22_add_user_email.py +35 -0
  82. taguette/migrations/versions/91ade71ccf4d_add_user_language.py +28 -0
  83. taguette/migrations/versions/955db2e523d1_add_collections_tables_and_associations_.py +60 -0
  84. taguette/migrations/versions/a1b2c3d4e5f6_add_user_hide_code_counts.py +28 -0
  85. taguette/migrations/versions/b23f3b7a638e_add_user_password_change_date.py +36 -0
  86. taguette/migrations/versions/b7c1e2d3f4a5_add_project_compact_layout.py +28 -0
  87. taguette/migrations/versions/bc8e0e0677e9_rename_command_fields.py +126 -0
  88. taguette/migrations/versions/bce44849c2f2_lowercase_logins.py +96 -0
  89. taguette/migrations/versions/ca076140922f_update_user_for_external_logins.py +32 -0
  90. taguette/migrations/versions/d86c45d7aa8a_add_document_direction.py +127 -0
  91. taguette/migrations/versions/db5e31a0233d_remove_blank_highlights.py +88 -0
  92. taguette/migrations/versions/dd37d9027a24_unique_tags.py +68 -0
  93. taguette/migrations/versions/de678cef2a94_add_project_id_to_collections_and_.py +41 -0
  94. taguette/migrations/versions/e459991d960e_add_table_edugainidps.py +39 -0
  95. taguette/migrations/versions/e4cf92942271_add_index.py +29 -0
  96. taguette/migrations/versions/e4e090a5b511_remove_commands_document_id_fk.py +38 -0
  97. taguette/migrations/versions/e9a9f1c77971_add_favorite_column_to_document.py +32 -0
  98. taguette/migrations/versions/ecb4065de575_don_t_use_server_default_now_timezone_.py +44 -0
  99. taguette/migrations/versions/fbdc29566f62_edugain_fix_field_type.py +42 -0
  100. taguette/migrations/versions/fdc6eb54b034_add_parent_id_column_to_tags_table.py +31 -0
  101. taguette/static/README.md +34 -0
  102. taguette/static/alt_templates/.gitkeep +0 -0
  103. taguette/static/assets/test/logos/monsters-university-logo.png +0 -0
  104. taguette/static/css/custom.css +1696 -0
  105. taguette/static/css/fa-all.min.css +5 -0
  106. taguette/static/css/themed.css +3 -0
  107. taguette/static/css/themed.css.map +25 -0
  108. taguette/static/css/vendor/bootstrap-treeview.min.css +1 -0
  109. taguette/static/css/vendor/bootstrap.min.css +6 -0
  110. taguette/static/css/vendor/font/context-menu-icons.eot +0 -0
  111. taguette/static/css/vendor/font/context-menu-icons.ttf +0 -0
  112. taguette/static/css/vendor/font/context-menu-icons.woff +0 -0
  113. taguette/static/css/vendor/font/context-menu-icons.woff2 +0 -0
  114. taguette/static/css/vendor/hierarchy-select.min.css +1 -0
  115. taguette/static/css/vendor/introjs.min.css +2 -0
  116. taguette/static/css/vendor/jquery.contextMenu.min.css +16 -0
  117. taguette/static/favicon.ico +0 -0
  118. taguette/static/js/codebook-viz.js +428 -0
  119. taguette/static/js/collection/context-menu.js +180 -0
  120. taguette/static/js/collection/hierarchy-select.js +71 -0
  121. taguette/static/js/collection/manager.js +217 -0
  122. taguette/static/js/document/context-menu.js +92 -0
  123. taguette/static/js/document/custom-select.js +82 -0
  124. taguette/static/js/document/manager.js +943 -0
  125. taguette/static/js/document/treeview.js +593 -0
  126. taguette/static/js/highlight/README.md +18 -0
  127. taguette/static/js/highlight/crud.js +119 -0
  128. taguette/static/js/highlight/extracts.js +497 -0
  129. taguette/static/js/highlight/loader.js +109 -0
  130. taguette/static/js/highlight/renderer.js +405 -0
  131. taguette/static/js/login.js +15 -0
  132. taguette/static/js/permissions.js +153 -0
  133. taguette/static/js/polling-event.js +145 -0
  134. taguette/static/js/project/intro.js +524 -0
  135. taguette/static/js/project/manager.js +0 -0
  136. taguette/static/js/project/search.js +124 -0
  137. taguette/static/js/tag/context-menu.js +133 -0
  138. taguette/static/js/tag/explore-codes.js +400 -0
  139. taguette/static/js/tag/hierarchy-select.js +69 -0
  140. taguette/static/js/tag/manager.js +545 -0
  141. taguette/static/js/tag/treeview.js +613 -0
  142. taguette/static/js/taguette.js +1790 -0
  143. taguette/static/js/utilities.js +714 -0
  144. taguette/static/js/vendor/bootstrap-treeview-custum.js +421 -0
  145. taguette/static/js/vendor/bootstrap-treeview-custum.min.js +1 -0
  146. taguette/static/js/vendor/bootstrap-treeview-default.min.js +1 -0
  147. taguette/static/js/vendor/bootstrap.bundle.min.js +7 -0
  148. taguette/static/js/vendor/bootstrap.bundle.min.js.map +1 -0
  149. taguette/static/js/vendor/hierarchy-select.min.js +1 -0
  150. taguette/static/js/vendor/introjs.min.js +17 -0
  151. taguette/static/js/vendor/jquery-3.7.1.js +2 -0
  152. taguette/static/js/vendor/jquery.contextMenu.min.js +2 -0
  153. taguette/static/libreqda.ico +0 -0
  154. taguette/static/logo-h.png +0 -0
  155. taguette/static/logo.png +0 -0
  156. taguette/static/logo_blanc.png +0 -0
  157. taguette/static/missing.png +0 -0
  158. taguette/static/robots.txt +2 -0
  159. taguette/static/scss/components/_badge.scss +42 -0
  160. taguette/static/scss/components/_button.scss +169 -0
  161. taguette/static/scss/components/_checkbox.scss +40 -0
  162. taguette/static/scss/components/_context_menu.scss +28 -0
  163. taguette/static/scss/components/_custom_select.scss +150 -0
  164. taguette/static/scss/components/_dropdown.scss +43 -0
  165. taguette/static/scss/components/_form.scss +54 -0
  166. taguette/static/scss/components/_modal.scss +57 -0
  167. taguette/static/scss/components/_project_card.scss +163 -0
  168. taguette/static/scss/components/_tag.scss +308 -0
  169. taguette/static/scss/components/_treeview.scss +76 -0
  170. taguette/static/scss/custom.scss +809 -0
  171. taguette/static/scss/layout/_credits.scss +62 -0
  172. taguette/static/scss/layout/_footer.scss +6 -0
  173. taguette/static/scss/layout/_navigation.scss +165 -0
  174. taguette/static/scss/layout/_sidebar.scss +37 -0
  175. taguette/static/scss/themes/default/_variables.scss +103 -0
  176. taguette/static/scss/themes/default/theme.css +3 -0
  177. taguette/static/scss/themes/default/theme.css.map +26 -0
  178. taguette/static/scss/themes/default/theme.scss +4 -0
  179. taguette/static/webfonts/BadScript-OFL.txt +94 -0
  180. taguette/static/webfonts/BadScript.ttf +0 -0
  181. taguette/static/webfonts/Montserrat-Light.ttf +0 -0
  182. taguette/static/webfonts/Montserrat-OFL.txt +93 -0
  183. taguette/static/webfonts/fa-brands-400.eot +0 -0
  184. taguette/static/webfonts/fa-brands-400.svg +1184 -0
  185. taguette/static/webfonts/fa-brands-400.ttf +0 -0
  186. taguette/static/webfonts/fa-brands-400.woff +0 -0
  187. taguette/static/webfonts/fa-brands-400.woff2 +0 -0
  188. taguette/static/webfonts/fa-regular-400.eot +0 -0
  189. taguette/static/webfonts/fa-regular-400.svg +467 -0
  190. taguette/static/webfonts/fa-regular-400.ttf +0 -0
  191. taguette/static/webfonts/fa-regular-400.woff +0 -0
  192. taguette/static/webfonts/fa-regular-400.woff2 +0 -0
  193. taguette/static/webfonts/fa-solid-900.eot +0 -0
  194. taguette/static/webfonts/fa-solid-900.svg +2618 -0
  195. taguette/static/webfonts/fa-solid-900.ttf +0 -0
  196. taguette/static/webfonts/fa-solid-900.woff +0 -0
  197. taguette/static/webfonts/fa-solid-900.woff2 +0 -0
  198. taguette/templates/alt_templates/.gitkeep +0 -0
  199. taguette/templates/archived_projects.html +50 -0
  200. taguette/templates/auth/account.html +74 -0
  201. taguette/templates/auth/cilogon.login.html +89 -0
  202. taguette/templates/auth/email_reset_password.html +5 -0
  203. taguette/templates/auth/external_account.html +60 -0
  204. taguette/templates/auth/login.html +144 -0
  205. taguette/templates/auth/reset_password.html +27 -0
  206. taguette/templates/auth/token_needed.html +7 -0
  207. taguette/templates/base.html +209 -0
  208. taguette/templates/bug_report.html +158 -0
  209. taguette/templates/cookies_prompt.html +15 -0
  210. taguette/templates/downloads.html +127 -0
  211. taguette/templates/email_bug_report.txt +9 -0
  212. taguette/templates/email_reset_password.txt +5 -0
  213. taguette/templates/error.html +8 -0
  214. taguette/templates/export_codebook.html +20 -0
  215. taguette/templates/export_document.html +20 -0
  216. taguette/templates/export_highlights.html +47 -0
  217. taguette/templates/index.html +347 -0
  218. taguette/templates/maintenance.html +8 -0
  219. taguette/templates/messages.js +74 -0
  220. taguette/templates/modal/change_document.html +68 -0
  221. taguette/templates/modal/create_collection.html +100 -0
  222. taguette/templates/modal/create_document.html +84 -0
  223. taguette/templates/modal/create_highlight.html +38 -0
  224. taguette/templates/modal/create_tag.html +73 -0
  225. taguette/templates/modal/explore_codes.html +58 -0
  226. taguette/templates/modal/manage_collaborators.html +44 -0
  227. taguette/templates/modal/merge_tag.html +49 -0
  228. taguette/templates/new_password.html +32 -0
  229. taguette/templates/partials/alert.html +16 -0
  230. taguette/templates/partials/codebook_viz_modal.html +34 -0
  231. taguette/templates/partials/confirm.html +17 -0
  232. taguette/templates/partials/document_toolbar.html +37 -0
  233. taguette/templates/partials/hlinfo.html +13 -0
  234. taguette/templates/partials/project_card.html +44 -0
  235. taguette/templates/partials/project_card_archived.html +41 -0
  236. taguette/templates/partials/project_sidebar.html +99 -0
  237. taguette/templates/partials/spinner.html +11 -0
  238. taguette/templates/permissions.html +54 -0
  239. taguette/templates/project.html +288 -0
  240. taguette/templates/project_delete.html +17 -0
  241. taguette/templates/project_import.html +122 -0
  242. taguette/templates/project_import_codebook.html +34 -0
  243. taguette/templates/project_import_codebook_confirm.html +49 -0
  244. taguette/templates/project_new.html +31 -0
  245. taguette/templates/tos.html +8 -0
  246. taguette/templates/trans.js +7 -0
  247. taguette/templates/welcome.html +15 -0
  248. taguette/utils.py +177 -0
  249. taguette/validate.py +141 -0
  250. taguette/version_check.py +102 -0
  251. taguette/web/__init__.py +252 -0
  252. taguette/web/api.py +1835 -0
  253. taguette/web/base.py +864 -0
  254. taguette/web/export.py +338 -0
  255. taguette/web/views.py +1618 -0
@@ -0,0 +1,72 @@
1
+ from __future__ import with_statement
2
+ from alembic import context
3
+ import logging
4
+ from sqlalchemy import create_engine
5
+ import taguette.database
6
+
7
+
8
+ # this is the Alembic Config object, which provides
9
+ # access to the values within the .ini file in use.
10
+ config = context.config
11
+
12
+ # Interpret the config file for Python logging.
13
+ # This line sets up loggers basically.
14
+ logging.basicConfig(level=logging.INFO)
15
+
16
+ # add your model's MetaData object here
17
+ # for 'autogenerate' support
18
+ target_metadata = taguette.database.Base.metadata
19
+
20
+
21
+ xargs = context.get_x_argument(as_dictionary=True)
22
+ if 'db' in xargs:
23
+ config.set_main_option('sqlalchemy.url', xargs['db'])
24
+
25
+
26
+ def run_migrations_offline():
27
+ """Run migrations in 'offline' mode.
28
+
29
+ This configures the context with just a URL
30
+ and not an Engine, though an Engine is acceptable
31
+ here as well. By skipping the Engine creation
32
+ we don't even need a DBAPI to be available.
33
+
34
+ Calls to context.execute() here emit the given string to the
35
+ script output.
36
+
37
+ """
38
+ url = config.get_main_option('sqlalchemy.url')
39
+ context.configure(
40
+ url=url, target_metadata=target_metadata, literal_binds=True,
41
+ render_as_batch=True,
42
+ )
43
+
44
+ with context.begin_transaction():
45
+ context.run_migrations()
46
+
47
+
48
+ def run_migrations_online():
49
+ """Run migrations in 'online' mode.
50
+
51
+ In this scenario we need to create an Engine
52
+ and associate a connection with the context.
53
+
54
+ """
55
+ url = config.get_main_option('sqlalchemy.url')
56
+ connectable = create_engine(url)
57
+
58
+ with connectable.connect() as connection:
59
+ context.configure(
60
+ connection=connection,
61
+ target_metadata=target_metadata,
62
+ render_as_batch=True,
63
+ )
64
+
65
+ with context.begin_transaction():
66
+ context.run_migrations()
67
+
68
+
69
+ if context.is_offline_mode():
70
+ run_migrations_offline()
71
+ else:
72
+ run_migrations_online()
@@ -0,0 +1,24 @@
1
+ """${message}
2
+
3
+ Revision ID: ${up_revision}
4
+ Revises: ${down_revision | comma,n}
5
+ Create Date: ${create_date}
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+ ${imports if imports else ""}
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = ${repr(up_revision)}
14
+ down_revision = ${repr(down_revision)}
15
+ branch_labels = ${repr(branch_labels)}
16
+ depends_on = ${repr(depends_on)}
17
+
18
+
19
+ def upgrade():
20
+ ${upgrades if upgrades else "pass"}
21
+
22
+
23
+ def downgrade():
24
+ ${downgrades if downgrades else "pass"}
@@ -0,0 +1,39 @@
1
+ """make documents.filename NOT NULL
2
+
3
+ Revision ID: 09c662cd9483
4
+ Revises: e4cf92942271
5
+ Create Date: 2022-01-21 17:42:53.265226
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '09c662cd9483'
14
+ down_revision = 'e4cf92942271'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ op.execute(
21
+ '''\
22
+ UPDATE documents SET filename = 'unknown' WHERE filename IS NULL;
23
+ ''',
24
+ )
25
+ with op.batch_alter_table('documents') as batch_op:
26
+ batch_op.alter_column(
27
+ 'filename',
28
+ existing_type=sa.VARCHAR(length=200),
29
+ nullable=False,
30
+ )
31
+
32
+
33
+ def downgrade():
34
+ with op.batch_alter_table('documents') as batch_op:
35
+ batch_op.alter_column(
36
+ 'filename',
37
+ existing_type=sa.VARCHAR(length=200),
38
+ nullable=True,
39
+ )
@@ -0,0 +1,55 @@
1
+ """add user roles
2
+
3
+ Revision ID: 1b29e68900c1
4
+ Revises: e9a9f1c77971
5
+ Create Date: 2025-03-10 08:14:24.098419
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+ from sqlalchemy.dialects import postgresql
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = '1b29e68900c1'
15
+ down_revision = 'e9a9f1c77971'
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ def upgrade():
21
+ connection = op.get_bind()
22
+ if connection.dialect.name == 'postgresql':
23
+ roles_enum = postgresql.ENUM(
24
+ 'ADMIN', 'PROJECT_ADMIN', 'TEAM_MEMBER', 'PROJECT_OWNER',
25
+ name='roles',
26
+ create_type=False,
27
+ )
28
+ roles_enum.create(connection)
29
+ else:
30
+ roles_enum = sa.Enum(
31
+ 'ADMIN', 'PROJECT_ADMIN', 'TEAM_MEMBER',
32
+ name='roles',
33
+ )
34
+
35
+ op.add_column(
36
+ 'users',
37
+ sa.Column('role', roles_enum, nullable=True)
38
+ )
39
+ op.execute(
40
+ '''\
41
+ UPDATE users SET role = 'PROJECT_ADMIN';
42
+ ''',
43
+ )
44
+
45
+ with op.batch_alter_table('users', schema=None) as batch_op:
46
+ batch_op.alter_column('role', nullable=False)
47
+
48
+
49
+ def downgrade():
50
+ with op.batch_alter_table('users', schema=None) as batch_op:
51
+ batch_op.drop_column('roles')
52
+
53
+ connection = op.get_bind()
54
+ if connection.dialect.name == 'postgresql':
55
+ op.execute("DROP TYPE roles;")
@@ -0,0 +1,34 @@
1
+ """update user to have a display name
2
+
3
+ Revision ID: 1b96a606551d
4
+ Revises: ca076140922f
5
+ Create Date: 2024-03-08 10:11:58.436815
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '1b96a606551d'
14
+ down_revision = 'ca076140922f'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table('users', schema=None) as batch_op:
22
+ batch_op.add_column(
23
+ sa.Column('displayname', sa.String(length=255),
24
+ nullable=True))
25
+
26
+ # ### end Alembic commands ###
27
+
28
+
29
+ def downgrade():
30
+ # ### commands auto generated by Alembic - please adjust! ###
31
+ with op.batch_alter_table('users', schema=None) as batch_op:
32
+ batch_op.drop_column('displayname')
33
+
34
+ # ### end Alembic commands ###
@@ -0,0 +1,33 @@
1
+ """Add color column to tags table
2
+
3
+ Revision ID: 2467bab602b7
4
+ Revises: fdc6eb54b034
5
+ Create Date: 2024-02-08 23:07:22.459389
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '2467bab602b7'
14
+ down_revision = 'fdc6eb54b034'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ # ### commands auto generated by Alembic - please adjust! ###
21
+ with op.batch_alter_table('tags', schema=None) as batch_op:
22
+ batch_op.add_column(sa.Column('color', sa.String(length=20),
23
+ nullable=False, server_default=''))
24
+
25
+ # ### end Alembic commands ###
26
+
27
+
28
+ def downgrade():
29
+ # ### commands auto generated by Alembic - please adjust! ###
30
+ with op.batch_alter_table('tags', schema=None) as batch_op:
31
+ batch_op.drop_column('color')
32
+
33
+ # ### end Alembic commands ###
@@ -0,0 +1,66 @@
1
+ """add user disabled
2
+
3
+ Revision ID: 382db36f20f4
4
+ Revises: 09c662cd9483
5
+ Create Date: 2022-05-14 23:33:03.709256
6
+
7
+ """
8
+ from alembic import op
9
+ from datetime import datetime
10
+ import sqlalchemy as sa
11
+
12
+
13
+ # revision identifiers, used by Alembic.
14
+ revision = '382db36f20f4'
15
+ down_revision = '6489b5f9cfb5'
16
+ branch_labels = None
17
+ depends_on = None
18
+
19
+
20
+ meta = sa.MetaData(naming_convention={
21
+ "ix": "ix_%(column_0_label)s",
22
+ "uq": "uq_%(table_name)s_%(column_0_name)s",
23
+ "ck": "ck_%(table_name)s_%(constraint_name)s",
24
+ "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
25
+ "pk": "pk_%(table_name)s",
26
+ })
27
+
28
+
29
+ def upgrade():
30
+ # Add column as NULL
31
+ with op.batch_alter_table('users', schema=None) as batch_op:
32
+ batch_op.add_column(sa.Column('disabled', sa.Boolean(), nullable=True))
33
+
34
+ users = sa.Table(
35
+ 'users',
36
+ meta,
37
+ sa.Column('login', sa.String(30), primary_key=True),
38
+ sa.Column('created', sa.DateTime, nullable=False,
39
+ default=lambda: datetime.utcnow()),
40
+ sa.Column('hashed_password', sa.String(120), nullable=True),
41
+ sa.Column('disabled', sa.Boolean, nullable=False, default=False),
42
+ sa.Column('password_set_date', sa.DateTime, nullable=True),
43
+ sa.Column('language', sa.String(10), nullable=True),
44
+ sa.Column('email', sa.String(256), nullable=True,
45
+ index=True, unique=True),
46
+ sa.Column('email_sent', sa.DateTime, nullable=True),
47
+ )
48
+
49
+ # Set all values to False
50
+ connection = op.get_bind()
51
+ assert connection is not None
52
+ with connection.begin():
53
+ connection.execute(users.update().values(disabled=False))
54
+
55
+ # Set column to NOT NULL
56
+ with op.batch_alter_table('users', schema=None) as batch_op:
57
+ batch_op.alter_column(
58
+ 'disabled',
59
+ existing_type=sa.BOOLEAN(),
60
+ nullable=False,
61
+ )
62
+
63
+
64
+ def downgrade():
65
+ with op.batch_alter_table('users', schema=None) as batch_op:
66
+ batch_op.drop_column('disabled')
@@ -0,0 +1,81 @@
1
+ """remove document groups
2
+
3
+ Revision ID: 43d6c240309d
4
+ Revises: bc8e0e0677e9
5
+ Create Date: 2021-07-14 17:54:23.308674
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '43d6c240309d'
14
+ down_revision = 'bc8e0e0677e9'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ op.drop_table('document_groups')
21
+
22
+ op.drop_index('ix_groups_path')
23
+ op.drop_index('ix_groups_project_id')
24
+ op.drop_table('groups')
25
+
26
+
27
+ def downgrade():
28
+ op.create_table(
29
+ 'groups',
30
+ sa.Column('id', sa.INTEGER(), nullable=False),
31
+ sa.Column('project_id', sa.INTEGER(), nullable=False),
32
+ sa.Column('path', sa.VARCHAR(length=200), nullable=False),
33
+ sa.Column('description', sa.TEXT(), nullable=False),
34
+ sa.ForeignKeyConstraint(
35
+ ['project_id'],
36
+ ['projects.id'],
37
+ name='fk_groups_project_id_projects',
38
+ ondelete='CASCADE',
39
+ ),
40
+ sa.PrimaryKeyConstraint('id'),
41
+ sa.UniqueConstraint(
42
+ 'project_id',
43
+ 'path',
44
+ name='uq_groups_project_id',
45
+ ),
46
+ )
47
+ op.create_index(
48
+ 'ix_groups_project_id',
49
+ 'groups',
50
+ ['project_id'],
51
+ unique=False,
52
+ )
53
+ op.create_index(
54
+ 'ix_groups_path',
55
+ 'groups',
56
+ ['path'],
57
+ unique=False,
58
+ )
59
+
60
+ op.create_table(
61
+ 'document_groups',
62
+ sa.Column('document_id', sa.INTEGER(), nullable=False),
63
+ sa.Column('group_id', sa.INTEGER(), nullable=False),
64
+ sa.ForeignKeyConstraint(
65
+ ['document_id'],
66
+ ['documents.id'],
67
+ name='fk_document_groups_document_id_documents',
68
+ ondelete='CASCADE',
69
+ ),
70
+ sa.ForeignKeyConstraint(
71
+ ['group_id'],
72
+ ['groups.id'],
73
+ name='fk_document_groups_group_id_groups',
74
+ ondelete='CASCADE',
75
+ ),
76
+ sa.PrimaryKeyConstraint(
77
+ 'document_id',
78
+ 'group_id',
79
+ name='pk_document_groups',
80
+ ),
81
+ )
@@ -0,0 +1,40 @@
1
+ """cascades
2
+
3
+ Revision ID: 447d636f72c5
4
+ Revises: 80b1cc9d4c22
5
+ Create Date: 2018-11-17 13:50:51.570871
6
+
7
+ """
8
+ from alembic import op
9
+
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = '447d636f72c5'
13
+ down_revision = '80b1cc9d4c22'
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade():
19
+ with op.batch_alter_table('commands') as batch_op:
20
+ batch_op.drop_constraint(
21
+ 'fk_commands_project_id_projects',
22
+ type_='foreignkey',
23
+ )
24
+ batch_op.create_foreign_key(
25
+ batch_op.f('fk_commands_project_id_projects'),
26
+ 'projects', ['project_id'], ['id'],
27
+ ondelete='CASCADE',
28
+ )
29
+
30
+
31
+ def downgrade():
32
+ with op.batch_alter_table('commands') as batch_op:
33
+ batch_op.drop_constraint(
34
+ batch_op.f('fk_commands_project_id_projects'),
35
+ type_='foreignkey',
36
+ )
37
+ batch_op.create_foreign_key(
38
+ 'fk_commands_project_id_projects',
39
+ 'projects', ['project_id'], ['id'],
40
+ )
@@ -0,0 +1,51 @@
1
+ """add more indexes
2
+
3
+ Revision ID: 491de2dc7cd7
4
+ Revises: d86c45d7aa8a
5
+ Create Date: 2021-11-09 16:50:41.582391
6
+
7
+ """
8
+ from alembic import op
9
+
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = '491de2dc7cd7'
13
+ down_revision = 'd86c45d7aa8a'
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade():
19
+ with op.batch_alter_table('commands', schema=None) as batch_op:
20
+ batch_op.create_index(
21
+ batch_op.f('ix_commands_document_id'),
22
+ ['document_id'],
23
+ unique=False,
24
+ )
25
+ batch_op.create_index(
26
+ batch_op.f('ix_commands_user_login'),
27
+ ['user_login'],
28
+ unique=False,
29
+ )
30
+
31
+ with op.batch_alter_table('highlight_tags', schema=None) as batch_op:
32
+ batch_op.create_index(
33
+ batch_op.f('ix_highlight_tags_highlight_id'),
34
+ ['highlight_id'],
35
+ unique=False,
36
+ )
37
+ batch_op.create_index(
38
+ batch_op.f('ix_highlight_tags_tag_id'),
39
+ ['tag_id'],
40
+ unique=False,
41
+ )
42
+
43
+
44
+ def downgrade():
45
+ with op.batch_alter_table('highlight_tags', schema=None) as batch_op:
46
+ batch_op.drop_index(batch_op.f('ix_highlight_tags_tag_id'))
47
+ batch_op.drop_index(batch_op.f('ix_highlight_tags_highlight_id'))
48
+
49
+ with op.batch_alter_table('commands', schema=None) as batch_op:
50
+ batch_op.drop_index(batch_op.f('ix_commands_user_login'))
51
+ batch_op.drop_index(batch_op.f('ix_commands_document_id'))
@@ -0,0 +1,58 @@
1
+ """user login length
2
+
3
+ Revision ID: 4c55b3b3ff30
4
+ Revises: 1b96a606551d
5
+ Create Date: 2024-03-11 09:31:27.003711
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+ import logging
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision = '4c55b3b3ff30'
16
+ down_revision = '1b96a606551d'
17
+ branch_labels = None
18
+ depends_on = None
19
+
20
+
21
+ def upgrade():
22
+ db_url = op.get_context().config.get_section('alembic')['sqlalchemy.url']
23
+ if db_url.startswith('sqlite:'):
24
+ # SQLite doesn't mind field length
25
+ logger.info(f"Skipping upgrade {revision} for SQLite")
26
+ else:
27
+ op.alter_column('users', 'login',
28
+ existing_type=sa.VARCHAR(length=30),
29
+ type_=sa.String(length=255),
30
+ existing_nullable=True)
31
+ op.alter_column('project_members', 'user_login',
32
+ existing_type=sa.VARCHAR(length=30),
33
+ type_=sa.String(length=255),
34
+ existing_nullable=True)
35
+ op.alter_column('commands', 'user_login',
36
+ existing_type=sa.VARCHAR(length=30),
37
+ type_=sa.String(length=255),
38
+ existing_nullable=True)
39
+
40
+
41
+ def downgrade():
42
+ db_url = op.get_context().config.get_section('alembic')['sqlalchemy.url']
43
+ if db_url.startswith('sqlite:'):
44
+ # SQLite doesn't mind field length
45
+ logger.info(f"Skipping downgrade {down_revision} for SQLite")
46
+ else:
47
+ op.alter_column('users', 'login',
48
+ existing_type=sa.VARCHAR(length=255),
49
+ type_=sa.String(length=30),
50
+ existing_nullable=True)
51
+ op.alter_column('project_members', 'user_login',
52
+ existing_type=sa.VARCHAR(length=255),
53
+ type_=sa.String(length=30),
54
+ existing_nullable=True)
55
+ op.alter_column('commands', 'user_login',
56
+ existing_type=sa.VARCHAR(length=255),
57
+ type_=sa.String(length=30),
58
+ existing_nullable=True)
@@ -0,0 +1,40 @@
1
+ """user with parent for permissions
2
+
3
+ Revision ID: 61a4abcc8769
4
+ Revises: 1b29e68900c1
5
+ Create Date: 2025-03-10 12:58:30.136770
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '61a4abcc8769'
14
+ down_revision = '1b29e68900c1'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ with op.batch_alter_table('users', schema=None) as batch_op:
21
+ batch_op.add_column(sa.Column('approved_by_user_login',
22
+ sa.String(length=255),
23
+ nullable=True))
24
+ batch_op.create_index(batch_op.f('ix_users_approved_by_user_login'),
25
+ ['approved_by_user_login'],
26
+ unique=False)
27
+ batch_op.create_foreign_key(
28
+ batch_op.f('fk_users_approved_by_user_login_users'),
29
+ 'users', ['approved_by_user_login'],
30
+ ['login'],
31
+ ondelete='CASCADE')
32
+
33
+
34
+ def downgrade():
35
+ with op.batch_alter_table('users', schema=None) as batch_op:
36
+ batch_op.drop_constraint(
37
+ batch_op.f('fk_users_approved_by_user_login_users'),
38
+ type_='foreignkey')
39
+ batch_op.drop_index(batch_op.f('ix_users_approved_by_user_login'))
40
+ batch_op.drop_column('approved_by_user_login')
@@ -0,0 +1,34 @@
1
+ """increase password hash size
2
+
3
+ Revision ID: 6489b5f9cfb5
4
+ Revises: 09c662cd9483
5
+ Create Date: 2022-10-06 17:17:36.212586
6
+
7
+ """
8
+ from alembic import op
9
+ import sqlalchemy as sa
10
+
11
+
12
+ # revision identifiers, used by Alembic.
13
+ revision = '6489b5f9cfb5'
14
+ down_revision = '09c662cd9483'
15
+ branch_labels = None
16
+ depends_on = None
17
+
18
+
19
+ def upgrade():
20
+ with op.batch_alter_table('users') as batch_op:
21
+ batch_op.alter_column(
22
+ 'hashed_password',
23
+ existing_type=sa.String(120),
24
+ type_=sa.String(192),
25
+ )
26
+
27
+
28
+ def downgrade():
29
+ with op.batch_alter_table('users') as batch_op:
30
+ batch_op.alter_column(
31
+ 'hashed_password',
32
+ existing_type=sa.String(192),
33
+ type_=sa.String(120),
34
+ )
@@ -0,0 +1,59 @@
1
+ """fix_unique_tags
2
+
3
+ Revision ID: 679f625e6e6a
4
+ Revises: dd37d9027a24
5
+ Create Date: 2018-11-12 17:20:50.420807
6
+
7
+ """
8
+ from alembic import op
9
+
10
+
11
+ # revision identifiers, used by Alembic.
12
+ revision = '679f625e6e6a'
13
+ down_revision = 'dd37d9027a24'
14
+ branch_labels = None
15
+ depends_on = None
16
+
17
+
18
+ def upgrade():
19
+ with op.batch_alter_table('tags') as batch_op:
20
+ batch_op.create_unique_constraint(
21
+ batch_op.f('uq_groups_project_id'),
22
+ ['project_id', 'path'],
23
+ )
24
+ batch_op.drop_index('ix_tags_path')
25
+ batch_op.create_index(
26
+ batch_op.f('ix_tags_path'),
27
+ ['path'],
28
+ unique=False,
29
+ )
30
+
31
+ with op.batch_alter_table('groups') as batch_op:
32
+ batch_op.create_unique_constraint(
33
+ batch_op.f('uq_groups_project_id'),
34
+ ['project_id', 'path'],
35
+ )
36
+ batch_op.drop_index('ix_groups_path')
37
+ batch_op.create_index(
38
+ batch_op.f('ix_groups_path'),
39
+ ['path'],
40
+ unique=False,
41
+ )
42
+
43
+
44
+ def downgrade():
45
+ with op.batch_alter_table('groups') as batch_op:
46
+ batch_op.drop_index(batch_op.f('ix_groups_path'))
47
+ batch_op.create_index('ix_groups_path', ['path'], unique=True)
48
+ batch_op.drop_constraint(
49
+ batch_op.f('uq_groups_project_id'),
50
+ type_='unique',
51
+ )
52
+
53
+ with op.batch_alter_table('tags') as batch_op:
54
+ batch_op.drop_index(batch_op.f('ix_tags_path'))
55
+ batch_op.create_index('ix_tags_path', ['path'], unique=True)
56
+ batch_op.drop_constraint(
57
+ batch_op.f('uq_groups_project_id'),
58
+ type_='unique',
59
+ )