- Add AdminRequired middleware to all /admin routes for proper authorization - Restrict admin panel, comments, users, settings to admin role only - Create separate /my/articles routes for regular users to manage their own articles - Add MyArticlesPage handler for users to view/edit/delete their own content - Update navigation menus with role-based visibility - Admin dropdown shows only 'Admin Panel' link, other features in dashboard - Regular users see 'My Articles' link in profile dropdown - Add i18n translations for 'my_articles' and 'comment_manage' keys - Fix permission boundary issues where author role could access admin settings Security improvements: - Platform settings now require admin role - Comment moderation requires admin role - User management requires admin role - Regular users can only manage their own articles Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61 lines
3.6 KiB
HTML
61 lines
3.6 KiB
HTML
{{define "my_articles"}}
|
|
{{template "header" .}}
|
|
<section class="max-w-5xl mx-auto px-4 py-12">
|
|
<div class="flex items-center justify-between mb-8">
|
|
<h2 class="text-3xl font-bold text-gray-900">{{index .Tr "my_articles_title"}}</h2>
|
|
<a href="/my/articles/new"
|
|
class="inline-flex items-center gap-2 bg-blue-600 text-white px-4 py-2 rounded-lg font-medium hover:bg-blue-700 transition-colors">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/>
|
|
</svg>
|
|
{{index .Tr "dash_new_article"}}
|
|
</a>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden">
|
|
<table class="w-full text-left">
|
|
<thead class="bg-gray-50 border-b border-gray-200">
|
|
<tr>
|
|
<th class="px-4 py-3 text-sm font-semibold text-gray-600">{{index .Tr "article_col_title"}}</th>
|
|
<th class="px-4 py-3 text-sm font-semibold text-gray-600">{{index .Tr "article_col_status"}}</th>
|
|
<th class="px-4 py-3 text-sm font-semibold text-gray-600">{{index .Tr "article_col_published"}}</th>
|
|
<th class="px-4 py-3 text-sm font-semibold text-gray-600 text-right">{{index .Tr "article_col_actions"}}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100">
|
|
{{range .Articles}}
|
|
<tr class="hover:bg-gray-50">
|
|
<td class="px-4 py-3 text-sm text-gray-800">
|
|
{{.Title}}
|
|
{{if .IsTop}}<span class="ml-1 text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded">{{index $.Tr "article_is_top"}}</span>{{end}}
|
|
</td>
|
|
<td class="px-4 py-3 text-sm">
|
|
{{if eq .Status 1}}<span class="text-xs bg-green-100 text-green-700 px-2 py-1 rounded">{{index $.Tr "article_published"}}</span>
|
|
{{else if eq .Status 2}}<span class="text-xs bg-gray-200 text-gray-600 px-2 py-1 rounded">{{index $.Tr "article_archived"}}</span>
|
|
{{else}}<span class="text-xs bg-yellow-100 text-yellow-700 px-2 py-1 rounded">{{index $.Tr "article_draft"}}</span>{{end}}
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-gray-500">
|
|
{{if .PublishedAt}}{{.PublishedAt.Format "2006-01-02 15:04"}}{{else}}—{{end}}
|
|
</td>
|
|
<td class="px-4 py-3 text-sm text-right whitespace-nowrap">
|
|
<a href="/my/articles/{{.ID}}/edit"
|
|
class="text-blue-600 hover:text-blue-800 font-medium mr-3">{{index $.Tr "article_edit"}}</a>
|
|
<form action="/my/articles/{{.ID}}/delete" method="post" class="inline"
|
|
onsubmit="return confirm('{{index $.Tr "article_delete_confirm"}}');">
|
|
<button type="submit"
|
|
class="text-red-600 hover:text-red-800 font-medium cursor-pointer bg-transparent border-none">{{index $.Tr "article_delete"}}</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr>
|
|
<td colspan="4" class="px-4 py-12 text-center text-gray-500">{{index .Tr "home_no_posts"}}</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
{{template "footer" .}}
|
|
{{end}}
|