focomy 0.1.113__tar.gz → 0.1.115__tar.gz

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 (210) hide show
  1. {focomy-0.1.113 → focomy-0.1.115}/PKG-INFO +1 -1
  2. {focomy-0.1.113 → focomy-0.1.115}/core/admin/routes.py +41 -0
  3. focomy-0.1.115/core/services/channel.py +58 -0
  4. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/dashboard.html +22 -0
  5. {focomy-0.1.113 → focomy-0.1.115}/pyproject.toml +1 -1
  6. {focomy-0.1.113 → focomy-0.1.115}/.gitignore +0 -0
  7. {focomy-0.1.113 → focomy-0.1.115}/LICENSE +0 -0
  8. {focomy-0.1.113 → focomy-0.1.115}/README.md +0 -0
  9. {focomy-0.1.113 → focomy-0.1.115}/core/__init__.py +0 -0
  10. {focomy-0.1.113 → focomy-0.1.115}/core/admin/__init__.py +0 -0
  11. {focomy-0.1.113 → focomy-0.1.115}/core/admin/url.py +0 -0
  12. {focomy-0.1.113 → focomy-0.1.115}/core/api/__init__.py +0 -0
  13. {focomy-0.1.113 → focomy-0.1.115}/core/api/auth.py +0 -0
  14. {focomy-0.1.113 → focomy-0.1.115}/core/api/comments.py +0 -0
  15. {focomy-0.1.113 → focomy-0.1.115}/core/api/entities.py +0 -0
  16. {focomy-0.1.113 → focomy-0.1.115}/core/api/forms.py +0 -0
  17. {focomy-0.1.113 → focomy-0.1.115}/core/api/media.py +0 -0
  18. {focomy-0.1.113 → focomy-0.1.115}/core/api/relations.py +0 -0
  19. {focomy-0.1.113 → focomy-0.1.115}/core/api/revisions.py +0 -0
  20. {focomy-0.1.113 → focomy-0.1.115}/core/api/schema.py +0 -0
  21. {focomy-0.1.113 → focomy-0.1.115}/core/api/search.py +0 -0
  22. {focomy-0.1.113 → focomy-0.1.115}/core/api/seo.py +0 -0
  23. {focomy-0.1.113 → focomy-0.1.115}/core/cli.py +0 -0
  24. {focomy-0.1.113 → focomy-0.1.115}/core/config.py +0 -0
  25. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/__init__.py +0 -0
  26. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/audit_log.yaml +0 -0
  27. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/category.yaml +0 -0
  28. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/channel.yaml +0 -0
  29. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/comment.yaml +0 -0
  30. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/edit_lock.yaml +0 -0
  31. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/form.yaml +0 -0
  32. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/form_submission.yaml +0 -0
  33. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/menu_item.yaml +0 -0
  34. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/news.yaml +0 -0
  35. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/page.yaml +0 -0
  36. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/plugin.yaml +0 -0
  37. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/plugin_developer.yaml +0 -0
  38. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/plugin_review.yaml +0 -0
  39. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/post.yaml +0 -0
  40. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/redirect.yaml +0 -0
  41. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/scheduled_action.yaml +0 -0
  42. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/series.yaml +0 -0
  43. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/site_setting.yaml +0 -0
  44. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/tag.yaml +0 -0
  45. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/user.yaml +0 -0
  46. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/widget.yaml +0 -0
  47. {focomy-0.1.113 → focomy-0.1.115}/core/content_types/workflow_history.yaml +0 -0
  48. {focomy-0.1.113 → focomy-0.1.115}/core/database.py +0 -0
  49. {focomy-0.1.113 → focomy-0.1.115}/core/engine/__init__.py +0 -0
  50. {focomy-0.1.113 → focomy-0.1.115}/core/engine/routes.py +0 -0
  51. {focomy-0.1.113 → focomy-0.1.115}/core/main.py +0 -0
  52. {focomy-0.1.113 → focomy-0.1.115}/core/migrations/env.py +0 -0
  53. {focomy-0.1.113 → focomy-0.1.115}/core/migrations/script.py.mako +0 -0
  54. {focomy-0.1.113 → focomy-0.1.115}/core/migrations/versions/2038bdf6693b_add_import_jobs_table.py +0 -0
  55. {focomy-0.1.113 → focomy-0.1.115}/core/migrations/versions/3a1b2c3d4e5f_add_file_hash_to_media.py +0 -0
  56. {focomy-0.1.113 → focomy-0.1.115}/core/models/__init__.py +0 -0
  57. {focomy-0.1.113 → focomy-0.1.115}/core/models/auth.py +0 -0
  58. {focomy-0.1.113 → focomy-0.1.115}/core/models/entity.py +0 -0
  59. {focomy-0.1.113 → focomy-0.1.115}/core/models/import_job.py +0 -0
  60. {focomy-0.1.113 → focomy-0.1.115}/core/models/media.py +0 -0
  61. {focomy-0.1.113 → focomy-0.1.115}/core/models/relation.py +0 -0
  62. {focomy-0.1.113 → focomy-0.1.115}/core/models/revision.py +0 -0
  63. {focomy-0.1.113 → focomy-0.1.115}/core/plugins/__init__.py +0 -0
  64. {focomy-0.1.113 → focomy-0.1.115}/core/plugins/base.py +0 -0
  65. {focomy-0.1.113 → focomy-0.1.115}/core/plugins/hooks.py +0 -0
  66. {focomy-0.1.113 → focomy-0.1.115}/core/plugins/loader.py +0 -0
  67. {focomy-0.1.113 → focomy-0.1.115}/core/plugins/manager.py +0 -0
  68. {focomy-0.1.113 → focomy-0.1.115}/core/rate_limit.py +0 -0
  69. {focomy-0.1.113 → focomy-0.1.115}/core/relations.yaml +0 -0
  70. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/.env.template +0 -0
  71. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/.gitignore.template +0 -0
  72. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/__init__.py +0 -0
  73. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/config.yaml.template +0 -0
  74. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/archive.html +0 -0
  75. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/base.html +0 -0
  76. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/category.html +0 -0
  77. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/home.html +0 -0
  78. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/post.html +0 -0
  79. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/templates/search.html +0 -0
  80. {focomy-0.1.113 → focomy-0.1.115}/core/scaffold/themes/default/theme.yaml +0 -0
  81. {focomy-0.1.113 → focomy-0.1.115}/core/schemas/__init__.py +0 -0
  82. {focomy-0.1.113 → focomy-0.1.115}/core/schemas/import_schema.py +0 -0
  83. {focomy-0.1.113 → focomy-0.1.115}/core/seo/__init__.py +0 -0
  84. {focomy-0.1.113 → focomy-0.1.115}/core/services/__init__.py +0 -0
  85. {focomy-0.1.113 → focomy-0.1.115}/core/services/api_auth.py +0 -0
  86. {focomy-0.1.113 → focomy-0.1.115}/core/services/assets.py +0 -0
  87. {focomy-0.1.113 → focomy-0.1.115}/core/services/audit.py +0 -0
  88. {focomy-0.1.113 → focomy-0.1.115}/core/services/auth.py +0 -0
  89. {focomy-0.1.113 → focomy-0.1.115}/core/services/block_converter.py +0 -0
  90. {focomy-0.1.113 → focomy-0.1.115}/core/services/bulk.py +0 -0
  91. {focomy-0.1.113 → focomy-0.1.115}/core/services/cache.py +0 -0
  92. {focomy-0.1.113 → focomy-0.1.115}/core/services/cleanup.py +0 -0
  93. {focomy-0.1.113 → focomy-0.1.115}/core/services/comment.py +0 -0
  94. {focomy-0.1.113 → focomy-0.1.115}/core/services/config_priority.py +0 -0
  95. {focomy-0.1.113 → focomy-0.1.115}/core/services/deployment.py +0 -0
  96. {focomy-0.1.113 → focomy-0.1.115}/core/services/edit_lock.py +0 -0
  97. {focomy-0.1.113 → focomy-0.1.115}/core/services/entity.py +0 -0
  98. {focomy-0.1.113 → focomy-0.1.115}/core/services/export.py +0 -0
  99. {focomy-0.1.113 → focomy-0.1.115}/core/services/field.py +0 -0
  100. {focomy-0.1.113 → focomy-0.1.115}/core/services/formula.py +0 -0
  101. {focomy-0.1.113 → focomy-0.1.115}/core/services/i18n.py +0 -0
  102. {focomy-0.1.113 → focomy-0.1.115}/core/services/index.py +0 -0
  103. {focomy-0.1.113 → focomy-0.1.115}/core/services/invite.py +0 -0
  104. {focomy-0.1.113 → focomy-0.1.115}/core/services/link_validator.py +0 -0
  105. {focomy-0.1.113 → focomy-0.1.115}/core/services/logging.py +0 -0
  106. {focomy-0.1.113 → focomy-0.1.115}/core/services/mail.py +0 -0
  107. {focomy-0.1.113 → focomy-0.1.115}/core/services/marketplace.py +0 -0
  108. {focomy-0.1.113 → focomy-0.1.115}/core/services/marketplace_verify.py +0 -0
  109. {focomy-0.1.113 → focomy-0.1.115}/core/services/media.py +0 -0
  110. {focomy-0.1.113 → focomy-0.1.115}/core/services/media_cleanup.py +0 -0
  111. {focomy-0.1.113 → focomy-0.1.115}/core/services/menu.py +0 -0
  112. {focomy-0.1.113 → focomy-0.1.115}/core/services/migration_helpers.py +0 -0
  113. {focomy-0.1.113 → focomy-0.1.115}/core/services/oauth.py +0 -0
  114. {focomy-0.1.113 → focomy-0.1.115}/core/services/pagination.py +0 -0
  115. {focomy-0.1.113 → focomy-0.1.115}/core/services/plugin_resolver.py +0 -0
  116. {focomy-0.1.113 → focomy-0.1.115}/core/services/plugin_sandbox.py +0 -0
  117. {focomy-0.1.113 → focomy-0.1.115}/core/services/preview.py +0 -0
  118. {focomy-0.1.113 → focomy-0.1.115}/core/services/query_optimizer.py +0 -0
  119. {focomy-0.1.113 → focomy-0.1.115}/core/services/rbac.py +0 -0
  120. {focomy-0.1.113 → focomy-0.1.115}/core/services/redirect.py +0 -0
  121. {focomy-0.1.113 → focomy-0.1.115}/core/services/relation.py +0 -0
  122. {focomy-0.1.113 → focomy-0.1.115}/core/services/revision.py +0 -0
  123. {focomy-0.1.113 → focomy-0.1.115}/core/services/routing.py +0 -0
  124. {focomy-0.1.113 → focomy-0.1.115}/core/services/sanitizer.py +0 -0
  125. {focomy-0.1.113 → focomy-0.1.115}/core/services/schedule.py +0 -0
  126. {focomy-0.1.113 → focomy-0.1.115}/core/services/search.py +0 -0
  127. {focomy-0.1.113 → focomy-0.1.115}/core/services/sentry.py +0 -0
  128. {focomy-0.1.113 → focomy-0.1.115}/core/services/seo.py +0 -0
  129. {focomy-0.1.113 → focomy-0.1.115}/core/services/settings.py +0 -0
  130. {focomy-0.1.113 → focomy-0.1.115}/core/services/spam_filter.py +0 -0
  131. {focomy-0.1.113 → focomy-0.1.115}/core/services/storage.py +0 -0
  132. {focomy-0.1.113 → focomy-0.1.115}/core/services/theme.py +0 -0
  133. {focomy-0.1.113 → focomy-0.1.115}/core/services/theme_inheritance.py +0 -0
  134. {focomy-0.1.113 → focomy-0.1.115}/core/services/thumbnail.py +0 -0
  135. {focomy-0.1.113 → focomy-0.1.115}/core/services/update.py +0 -0
  136. {focomy-0.1.113 → focomy-0.1.115}/core/services/widget.py +0 -0
  137. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/__init__.py +0 -0
  138. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/acf.py +0 -0
  139. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/analyzer.py +0 -0
  140. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/constants.py +0 -0
  141. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/content_sanitizer.py +0 -0
  142. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/diff_detector.py +0 -0
  143. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/dry_run.py +0 -0
  144. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/error_collector.py +0 -0
  145. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/id_resolver.py +0 -0
  146. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/import_service.py +0 -0
  147. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/importer.py +0 -0
  148. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/link_fixer.py +0 -0
  149. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/media.py +0 -0
  150. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/preview.py +0 -0
  151. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/redirects.py +0 -0
  152. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/rest_client.py +0 -0
  153. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/rollback.py +0 -0
  154. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/verification.py +0 -0
  155. {focomy-0.1.113 → focomy-0.1.115}/core/services/wordpress_import/wxr_parser.py +0 -0
  156. {focomy-0.1.113 → focomy-0.1.115}/core/services/workflow.py +0 -0
  157. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/backup.html +0 -0
  158. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/base.html +0 -0
  159. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/comments.html +0 -0
  160. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/components/editor.html +0 -0
  161. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/customize.html +0 -0
  162. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/entity_form.html +0 -0
  163. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/entity_list.html +0 -0
  164. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/forgot_password.html +0 -0
  165. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/import.html +0 -0
  166. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/link_validator.html +0 -0
  167. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/login.html +0 -0
  168. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/media.html +0 -0
  169. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/menus.html +0 -0
  170. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/plugins.html +0 -0
  171. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/redirects.html +0 -0
  172. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/reset_password.html +0 -0
  173. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/settings.html +0 -0
  174. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/sitemap.html +0 -0
  175. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/system.html +0 -0
  176. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/themes.html +0 -0
  177. {focomy-0.1.113 → focomy-0.1.115}/core/templates/admin/widgets.html +0 -0
  178. {focomy-0.1.113 → focomy-0.1.115}/core/themes/__init__.py +0 -0
  179. {focomy-0.1.113 → focomy-0.1.115}/core/themes/customizer.py +0 -0
  180. {focomy-0.1.113 → focomy-0.1.115}/core/themes/manager.py +0 -0
  181. {focomy-0.1.113 → focomy-0.1.115}/core/themes/marketplace.py +0 -0
  182. {focomy-0.1.113 → focomy-0.1.115}/core/utils.py +0 -0
  183. {focomy-0.1.113 → focomy-0.1.115}/static/favicon.svg +0 -0
  184. {focomy-0.1.113 → focomy-0.1.115}/themes/blog/templates/base.html +0 -0
  185. {focomy-0.1.113 → focomy-0.1.115}/themes/blog/templates/home.html +0 -0
  186. {focomy-0.1.113 → focomy-0.1.115}/themes/blog/templates/post.html +0 -0
  187. {focomy-0.1.113 → focomy-0.1.115}/themes/blog/theme.yaml +0 -0
  188. {focomy-0.1.113 → focomy-0.1.115}/themes/corporate/templates/base.html +0 -0
  189. {focomy-0.1.113 → focomy-0.1.115}/themes/corporate/templates/home.html +0 -0
  190. {focomy-0.1.113 → focomy-0.1.115}/themes/corporate/templates/page.html +0 -0
  191. {focomy-0.1.113 → focomy-0.1.115}/themes/corporate/theme.yaml +0 -0
  192. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/404.html +0 -0
  193. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/500.html +0 -0
  194. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/archive.html +0 -0
  195. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/base.html +0 -0
  196. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/category.html +0 -0
  197. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/channel.html +0 -0
  198. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/form.html +0 -0
  199. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/form_success.html +0 -0
  200. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/home.html +0 -0
  201. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/page.html +0 -0
  202. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/post.html +0 -0
  203. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/search.html +0 -0
  204. {focomy-0.1.113 → focomy-0.1.115}/themes/default/templates/series.html +0 -0
  205. {focomy-0.1.113 → focomy-0.1.115}/themes/default/theme.yaml +0 -0
  206. {focomy-0.1.113 → focomy-0.1.115}/themes/minimal/templates/base.html +0 -0
  207. {focomy-0.1.113 → focomy-0.1.115}/themes/minimal/templates/home.html +0 -0
  208. {focomy-0.1.113 → focomy-0.1.115}/themes/minimal/templates/page.html +0 -0
  209. {focomy-0.1.113 → focomy-0.1.115}/themes/minimal/templates/post.html +0 -0
  210. {focomy-0.1.113 → focomy-0.1.115}/themes/minimal/theme.yaml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: focomy
3
- Version: 0.1.113
3
+ Version: 0.1.115
4
4
  Summary: The Most Beautiful CMS - A metadata-driven, zero-duplicate-code content management system
5
5
  Project-URL: Homepage, https://github.com/focomy/focomy
6
6
  Project-URL: Documentation, https://focomy.dev/docs
@@ -589,11 +589,22 @@ async def dashboard(
589
589
  data["channel_title"] = channel_data.get("title")
590
590
  recent_posts.append(data)
591
591
 
592
+ # Check for updates
593
+ from ..services.update import update_service
594
+
595
+ update_info = await update_service.check_for_updates()
596
+
592
597
  context = await get_context(request, db, current_user, "dashboard")
593
598
  context.update(
594
599
  {
595
600
  "stats": stats,
596
601
  "recent_posts": recent_posts,
602
+ "update_info": {
603
+ "current_version": update_info.current_version,
604
+ "latest_version": update_info.latest_version,
605
+ "has_update": update_info.has_update,
606
+ "release_url": update_info.release_url,
607
+ },
597
608
  }
598
609
  )
599
610
 
@@ -4177,6 +4188,16 @@ async def entity_create(
4177
4188
  if rel_ids:
4178
4189
  await relation_svc.sync(entity.id, rel_ids, rel.type)
4179
4190
 
4191
+ # Auto-assign posts channel for post type if not specified
4192
+ if type_name == "post":
4193
+ rel_channel_values = form_data.getlist("rel_post_channel")
4194
+ channel_ids = [v for v in rel_channel_values if v]
4195
+ if not channel_ids:
4196
+ from ..services.channel import get_or_create_posts_channel
4197
+
4198
+ posts_channel_id = await get_or_create_posts_channel(db)
4199
+ await relation_svc.sync(entity.id, [posts_channel_id], "post_channel")
4200
+
4180
4201
  # Log create action
4181
4202
  audit_svc = AuditService(db)
4182
4203
  await audit_svc.log_create(
@@ -4484,6 +4505,16 @@ async def entity_delete(
4484
4505
  entity_data = entity_svc.serialize(entity)
4485
4506
  user_data = entity_svc.serialize(current_user)
4486
4507
 
4508
+ # Check if channel is protected from deletion
4509
+ if type_name == "channel":
4510
+ from ..services.channel import is_protected_channel
4511
+
4512
+ if is_protected_channel(entity_data.get("slug", "")):
4513
+ raise HTTPException(
4514
+ status_code=400,
4515
+ detail="postsチャンネルは削除できません",
4516
+ )
4517
+
4487
4518
  await entity_svc.delete(entity_id, user_id=user_data.get("id"))
4488
4519
 
4489
4520
  # Log delete action
@@ -4527,6 +4558,16 @@ async def entity_delete_post(
4527
4558
  entity_data = entity_svc.serialize(entity)
4528
4559
  user_data = entity_svc.serialize(current_user)
4529
4560
 
4561
+ # Check if channel is protected from deletion
4562
+ if type_name == "channel":
4563
+ from ..services.channel import is_protected_channel
4564
+
4565
+ if is_protected_channel(entity_data.get("slug", "")):
4566
+ raise HTTPException(
4567
+ status_code=400,
4568
+ detail="postsチャンネルは削除できません",
4569
+ )
4570
+
4530
4571
  await entity_svc.delete(entity_id, user_id=user_data.get("id"))
4531
4572
 
4532
4573
  # Log delete action
@@ -0,0 +1,58 @@
1
+ """Channel service - Default channel management."""
2
+
3
+ import structlog
4
+
5
+ from sqlalchemy.ext.asyncio import AsyncSession
6
+
7
+ from .entity import EntityService
8
+
9
+ logger = structlog.get_logger(__name__)
10
+
11
+ DEFAULT_CHANNEL_SLUG = "posts"
12
+
13
+
14
+ async def get_or_create_posts_channel(db: AsyncSession) -> str:
15
+ """Get or create the default 'posts' channel.
16
+
17
+ Returns:
18
+ Channel entity ID
19
+ """
20
+ entity_svc = EntityService(db)
21
+
22
+ # Try to find existing posts channel
23
+ entities = await entity_svc.find(
24
+ "channel",
25
+ filters={"slug": DEFAULT_CHANNEL_SLUG},
26
+ limit=1,
27
+ )
28
+
29
+ if entities:
30
+ channel_id = entities[0].id
31
+ logger.debug("found_posts_channel", channel_id=channel_id)
32
+ return channel_id
33
+
34
+ # Create posts channel
35
+ entity = await entity_svc.create(
36
+ "channel",
37
+ {
38
+ "title": "Posts",
39
+ "slug": DEFAULT_CHANNEL_SLUG,
40
+ "description": "Default channel for posts",
41
+ "sort_order": 0,
42
+ },
43
+ )
44
+
45
+ logger.info("created_posts_channel", channel_id=entity.id)
46
+ return entity.id
47
+
48
+
49
+ def is_protected_channel(slug: str) -> bool:
50
+ """Check if a channel is protected from deletion.
51
+
52
+ Args:
53
+ slug: Channel slug
54
+
55
+ Returns:
56
+ True if protected
57
+ """
58
+ return slug == DEFAULT_CHANNEL_SLUG
@@ -69,4 +69,26 @@
69
69
  </div>
70
70
  </div>
71
71
  </div>
72
+
73
+ <div class="grid grid-1 mt-4">
74
+ <div class="card">
75
+ <div class="card-header">
76
+ <h3 class="card-title">Focomy バージョン</h3>
77
+ </div>
78
+ <div class="card-body">
79
+ {% if update_info.has_update %}
80
+ <div class="alert alert-warning mb-2">
81
+ <strong>新バージョン {{ update_info.latest_version }} が利用可能です</strong>
82
+ {% if update_info.release_url %}
83
+ <a href="{{ update_info.release_url }}" target="_blank" class="ml-2">リリースノート →</a>
84
+ {% endif %}
85
+ </div>
86
+ <p class="text-muted mb-1">アップデート方法:</p>
87
+ <code>pip install --upgrade focomy</code>
88
+ {% else %}
89
+ <span class="badge badge-success">最新バージョン ({{ update_info.current_version }})</span>
90
+ {% endif %}
91
+ </div>
92
+ </div>
93
+ </div>
72
94
  {% endblock %}
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "focomy"
7
- version = "0.1.113"
7
+ version = "0.1.115"
8
8
  description = "The Most Beautiful CMS - A metadata-driven, zero-duplicate-code content management system"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes