封面图片
diff --git a/pages/editor/series.tsx b/pages/editor/series.tsx
index 665378d7..ad6699a9 100644
--- a/pages/editor/series.tsx
+++ b/pages/editor/series.tsx
@@ -1,4 +1,4 @@
-import { Text, Box, Heading, Image, HStack, Center, Button, Flex, FormControl, FormLabel, Input, FormErrorMessage, VStack, Textarea, Divider, useToast, Stack, StackDivider, useColorModeValue, Table, Thead, Tr, Th, Tbody, Td, CloseButton, Editable, EditablePreview, EditableInput } from "@chakra-ui/react"
+import { Text, Box, Heading, Image, HStack, Center, Button, Flex, FormControl, FormLabel, Input, FormErrorMessage, VStack, Textarea, Divider, useToast, Stack, StackDivider, useColorModeValue, Table, Thead, Tr, Th, Tbody, Td, CloseButton, Editable, EditablePreview, EditableInput, Select } from "@chakra-ui/react"
import Card from "components/card"
import Sidebar from "layouts/sidebar/sidebar"
import React, { useEffect, useState } from "react"
@@ -24,7 +24,7 @@ var validator = require('validator');
const newSeries: Story = { title: '', brief: '', cover: '', type: IDType.Series }
const PostsPage = () => {
- const [currentSeries, setCurrentSeries]:[Story,any] = useState(null)
+ const [currentSeries, setCurrentSeries]: [Story, any] = useState(null)
const [series, setSeries] = useState([])
const [posts, setPosts] = useState([])
const [seriesPosts, setSeriesPosts] = useState([])
@@ -80,7 +80,7 @@ const PostsPage = () => {
// 这里必须按照顺序同步提交
await requestApi.post(`/story`, values)
await requestApi.post(`/story/series/post/${values.id}`, seriesPosts)
-
+
toast({
description: "提交成功",
@@ -124,17 +124,17 @@ const PostsPage = () => {
setSeriesPosts(sposts)
}
- const onPriorityChange = (e,s) => {
+ const onPriorityChange = (e, s) => {
if (e.currentTarget.value) {
- const i = parseInt(e.currentTarget.value)
+ const i = parseInt(e.currentTarget.value)
if (i) {
s.priority = i
}
} else {
s.priority = 0
}
-
- const sposts = cloneDeep(seriesPosts)
+
+ const sposts = cloneDeep(seriesPosts)
setSeriesPosts(sposts)
}
@@ -174,6 +174,19 @@ const PostsPage = () => {
)}
+ {/*
+ {({ field, form }) => (
+
+ 发布于
+
+ {form.errors.ownerId}
+
+ )}
+ */}
{({ field, form }) => (
@@ -196,7 +209,7 @@ const PostsPage = () => {
{({ field, form }) => (
标签
- currentSeries.tags = ids}/>
+ currentSeries.tags = ids} />
)}
@@ -229,8 +242,8 @@ const PostsPage = () => {
{post.title} |
-
- onPriorityChange(e,s)}/>
+
+ onPriorityChange(e, s)} />
|
onPostDelete(s.id)} _focus={null} /> |
@@ -277,7 +290,7 @@ const PostsPage = () => {
{series.map(post =>
- editSeries(post)} onDelete={() => onDeleteSeries(post.id)} showSource={false} onPin={() => onPinPost(post.id)}/>
+ editSeries(post)} onDelete={() => onDeleteSeries(post.id)} showSource={false} onPin={() => onPinPost(post.id)} />
)}
diff --git a/server/internal/org/org.go b/server/internal/org/org.go
index 7994bab7..f977268b 100644
--- a/server/internal/org/org.go
+++ b/server/internal/org/org.go
@@ -111,3 +111,18 @@ func IsOrgAdmin(userID string, orgID string) bool {
return role.IsAdmin()
}
+
+func UserInOrg(userID string, orgID string) bool {
+ var role models.RoleType
+ err := db.Conn.QueryRow("SELECT role FROM org_member WHERE org_id=? and user_id=?", orgID, userID).Scan(&role)
+ if err != nil && err != sql.ErrNoRows {
+ logger.Warn("check is org admin error", "error", err)
+ return false
+ }
+
+ if err == sql.ErrNoRows {
+ return false
+ }
+
+ return true
+}
diff --git a/server/internal/storage/sql_tables.go b/server/internal/storage/sql_tables.go
index 837a5b6f..2a048188 100644
--- a/server/internal/storage/sql_tables.go
+++ b/server/internal/storage/sql_tables.go
@@ -66,6 +66,7 @@ var sqlTables = map[string]string{
id VARCHAR(255) PRIMARY KEY,
type VARCHAR(1) NOT NULL,
creator VARCHAR(255) NOT NULL,
+ owner VARCHAR(255) DEFAULT '',
slug VARCHAR(64) DEFAULT '',
title VARCHAR(255) DEFAULT '',
md TEXT DEFAULT '',
@@ -80,6 +81,8 @@ var sqlTables = map[string]string{
ON story (type);
CREATE INDEX IF NOT EXISTS story_creator
ON story (creator);
+ CREATE INDEX IF NOT EXISTS story_owner
+ ON story (owner);
CREATE INDEX IF NOT EXISTS story_created
ON story (created);
`,
diff --git a/server/internal/story/post.go b/server/internal/story/post.go
index bc7d05af..3e2fc7ac 100644
--- a/server/internal/story/post.go
+++ b/server/internal/story/post.go
@@ -11,6 +11,7 @@ import (
"github.com/asaskevich/govalidator"
"github.com/gin-gonic/gin"
"github.com/imdotdev/im.dev/server/internal/interaction"
+ "github.com/imdotdev/im.dev/server/internal/org"
"github.com/imdotdev/im.dev/server/internal/tags"
"github.com/imdotdev/im.dev/server/internal/user"
"github.com/imdotdev/im.dev/server/pkg/config"
@@ -70,6 +71,13 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
}
}
+ // check user is in org exist
+ if post.OwnerID != "" {
+ if !org.UserInOrg(user.ID, post.OwnerID) {
+ return nil, e.New(http.StatusForbidden, e.NoEditorPermission)
+ }
+ }
+
now := time.Now()
md := utils.Compress(post.Md)
@@ -83,8 +91,8 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
}
//create
- _, err := db.Conn.Exec("INSERT INTO story (id,type,creator,slug, title, md, url, cover, brief,status, created, updated) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)",
- post.ID, post.Type, user.ID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, models.StatusPublished, now, now)
+ _, err := db.Conn.Exec("INSERT INTO story (id,type,creator,owner,slug, title, md, url, cover, brief,status, created, updated) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)",
+ post.ID, post.Type, user.ID, post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, models.StatusPublished, now, now)
if err != nil {
logger.Warn("submit post error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal)
@@ -96,8 +104,8 @@ func SubmitStory(c *gin.Context) (map[string]string, *e.Error) {
return nil, e.New(http.StatusForbidden, e.NoEditorPermission)
}
- _, err = db.Conn.Exec("UPDATE story SET slug=?, title=?, md=?, url=?, cover=?, brief=?, updated=? WHERE id=?",
- post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, now, post.ID)
+ _, err = db.Conn.Exec("UPDATE story SET owner=?, slug=?, title=?, md=?, url=?, cover=?, brief=?, updated=? WHERE id=?",
+ post.OwnerID, post.Slug, post.Title, md, post.URL, post.Cover, post.Brief, now, post.ID)
if err != nil {
logger.Warn("upate post error", "error", err)
return nil, e.New(http.StatusInternalServerError, e.Internal)
@@ -205,8 +213,8 @@ func DeletePost(id string) *e.Error {
func GetStory(id string, slug string) (*models.Story, *e.Error) {
ar := &models.Story{}
var rawmd []byte
- err := db.Conn.QueryRow("select id,type,slug,title,md,url,cover,brief,creator,status,created,updated from story where id=?", id).Scan(
- &ar.ID, &ar.Type, &ar.Slug, &ar.Title, &rawmd, &ar.URL, &ar.Cover, &ar.Brief, &ar.CreatorID, &ar.Status, &ar.Created, &ar.Updated,
+ err := db.Conn.QueryRow("select id,type,slug,title,md,url,cover,brief,creator,owner,status,created,updated from story where id=?", id).Scan(
+ &ar.ID, &ar.Type, &ar.Slug, &ar.Title, &rawmd, &ar.URL, &ar.Cover, &ar.Brief, &ar.CreatorID, &ar.OwnerID, &ar.Status, &ar.Created, &ar.Updated,
)
if err != nil {
if err == sql.ErrNoRows {
@@ -218,8 +226,13 @@ func GetStory(id string, slug string) (*models.Story, *e.Error) {
md, _ := utils.Uncompress(rawmd)
ar.Md = string(md)
+
ar.Creator = &models.UserSimple{ID: ar.CreatorID}
err = ar.Creator.Query()
+ if ar.OwnerID != "" {
+ ar.Owner = &models.UserSimple{ID: ar.OwnerID}
+ err = ar.Owner.Query()
+ }
// get tags
t, rawTags, err := tags.GetTargetTags(ar.ID)
diff --git a/server/internal/story/posts.go b/server/internal/story/posts.go
index 10897110..e411c799 100644
--- a/server/internal/story/posts.go
+++ b/server/internal/story/posts.go
@@ -14,7 +14,7 @@ import (
"github.com/imdotdev/im.dev/server/pkg/models"
)
-const PostQueryPrefix = "select id,type,slug,title,url,cover,brief,creator,created,updated from story "
+const PostQueryPrefix = "select id,type,slug,title,url,cover,brief,creator,owner,created,updated from story "
func HomePosts(user *models.User, filter string) (models.Stories, *e.Error) {
@@ -144,7 +144,7 @@ func GetPosts(user *models.User, rows *sql.Rows) models.Stories {
posts := make(models.Stories, 0)
for rows.Next() {
ar := &models.Story{}
- err := rows.Scan(&ar.ID, &ar.Type, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.CreatorID, &ar.Created, &ar.Updated)
+ err := rows.Scan(&ar.ID, &ar.Type, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.CreatorID, &ar.OwnerID, &ar.Created, &ar.Updated)
if err != nil {
logger.Warn("scan post error", "error", err)
continue
@@ -155,6 +155,12 @@ func GetPosts(user *models.User, rows *sql.Rows) models.Stories {
creator.Query()
ar.Creator = creator
+ if ar.OwnerID != "" {
+ owner := &models.UserSimple{ID: ar.OwnerID}
+ owner.Query()
+ ar.Owner = owner
+ }
+
// 获取评论信息
ar.Comments = GetCommentCount(ar.ID)
diff --git a/server/pkg/models/story.go b/server/pkg/models/story.go
index 69549fe6..a6420a24 100644
--- a/server/pkg/models/story.go
+++ b/server/pkg/models/story.go
@@ -17,6 +17,8 @@ type Story struct {
Type string `json:"type"`
Creator *UserSimple `json:"creator"`
CreatorID string `json:"creatorId"`
+ Owner *UserSimple `json:"owner"`
+ OwnerID string `json:"ownerId"`
Title string `json:"title"`
Slug string `json:"slug"`
Md string `json:"md"`
diff --git a/src/components/story/story-author.tsx b/src/components/story/story-author.tsx
index 60e7ca9c..7976516f 100644
--- a/src/components/story/story-author.tsx
+++ b/src/components/story/story-author.tsx
@@ -21,8 +21,14 @@ export const StoryAuthor= ({story,showFooter=true,size='lg'}:Props) =>{
router.push(`/${story.creator.username}`)} cursor="pointer"/>
- router.push(`/${story.creator.username}`)} cursor="pointer">{story.creator.nickname === "" ? story.creator.username : story.creator.nickname}
- 发布于{moment(story.created).fromNow()}
+ {story.ownerId ?
+
+ {story.creator.nickname}
+ for
+ {story.owner.nickname}
+ :
+ router.push(`/${story.creator.username}`)} cursor="pointer">{story.creator.nickname === "" ? story.creator.username : story.creator.nickname}}
+ {moment(story.created).fromNow()}
{showFooter &&
4 min read
}
diff --git a/src/types/story.ts b/src/types/story.ts
index 543f88d2..a90e6ac4 100644
--- a/src/types/story.ts
+++ b/src/types/story.ts
@@ -14,6 +14,8 @@ export interface Story {
slug?: string
creator?: UserSimple
creatorId?: string
+ owner?: UserSimple
+ ownerId?:string
title?: string
md?: string
url?: string