1
0
mirror of https://github.com/fumiama/paper-manager.git synced 2026-06-12 12:10:25 +08:00

finish upload avatar

This commit is contained in:
源文雨
2023-03-18 00:25:19 +08:00
parent cd571e9e25
commit a072cfe1cf
18 changed files with 268 additions and 72 deletions

View File

@@ -1,26 +1,27 @@
package file package api
import ( import (
"net/http" "net/http"
"strings"
"github.com/fumiama/paper-manager/backend/global" "github.com/fumiama/paper-manager/backend/global"
"github.com/fumiama/paper-manager/backend/utils" "github.com/fumiama/paper-manager/backend/utils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// Handler serves contents in global.FileFolder // FileHandler serves contents in global.FileFolder
func Handler(w http.ResponseWriter, r *http.Request) { func FileHandler(w http.ResponseWriter, r *http.Request) {
if !utils.IsMethod("GET", w, r) { if !utils.IsMethod("GET", w, r) {
return return
} }
i := strings.LastIndex(r.URL.Path, "/") if r.URL.Path[0] != '/' {
fn := r.URL.Path[i+1:] r.URL.Path = "/" + r.URL.Path
}
fn := r.URL.Path[6:]
if fn == "" { if fn == "" {
http.Error(w, "400 Bad Request: empty path", http.StatusBadRequest) http.Error(w, "400 Bad Request: empty path", http.StatusBadRequest)
return return
} }
name := global.FileFolder + fn name := global.FileFolder + fn
logrus.Infoln("[file.Handler]\t serve", name) logrus.Infoln("[file.FileHandler] serve", name)
http.ServeFile(w, r, name) http.ServeFile(w, r, name)
} }

View File

@@ -52,9 +52,12 @@ func getLoginSalt(username string) (*saltinfo, error) {
return nil, errNoSuchUser return nil, errNoSuchUser
} }
s, _ := loginstatus.Load(username) s, _ := loginstatus.Load(username)
if s != loginStatusNo { if s == loginStatusYes {
return nil, errInvalidLoginStatus return nil, errInvalidLoginStatus
} }
if s >= loginStatusFailLast {
return nil, errTooManyFailedLogins
}
salt := loginsalts.Get(username) salt := loginsalts.Get(username)
if salt.count != nil { if salt.count != nil {
if atomic.AddUintptr(salt.count, 1) >= maxSaltCount { if atomic.AddUintptr(salt.count, 1) >= maxSaltCount {

View File

@@ -9,13 +9,16 @@ import (
// Handler serves all backend /api call // Handler serves all backend /api call
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path[0] != '/' {
r.URL.Path = "/" + r.URL.Path
}
if r.URL.Path == "/api/getLoginSalt" { if r.URL.Path == "/api/getLoginSalt" {
if !utils.IsMethod("GET", w, r) { if !utils.IsMethod("GET", w, r) {
return return
} }
username := r.URL.Query().Get("username") username := r.URL.Query().Get("username")
if username == "" { if username == "" {
http.Error(w, "400 Bad Request: empty username", http.StatusBadRequest) writeresult(w, codeError, nil, "empty username", typeError)
return return
} }
salt, err := getLoginSalt(username) salt, err := getLoginSalt(username)
@@ -58,6 +61,18 @@ func Handler(w http.ResponseWriter, r *http.Request) {
writeresult(w, codeSuccess, r, messageOk, typeSuccess) writeresult(w, codeSuccess, r, messageOk, typeSuccess)
return return
} }
if r.URL.Path == "/api/logout" {
if !utils.IsMethod("GET", w, r) {
return
}
err := logout(r.Header.Get("Authorization"))
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
writeresult(w, codeSuccess, nil, messageOk, typeSuccess)
return
}
if !utils.IsMethod("GET", w, r) { if !utils.IsMethod("GET", w, r) {
return return
} }

98
backend/api/upload.go Normal file
View File

@@ -0,0 +1,98 @@
package api
import (
"bytes"
"io"
"net/http"
"os"
"strconv"
"strings"
"github.com/fumiama/imgsz"
"github.com/sirupsen/logrus"
"github.com/fumiama/paper-manager/backend/global"
"github.com/fumiama/paper-manager/backend/utils"
)
type upload struct {
Message string `json:"message"`
Code int `json:"code"`
URL string `json:"url"`
}
// UploadHandler receives uploaded files
func UploadHandler(w http.ResponseWriter, r *http.Request) {
if !utils.IsMethod("POST", w, r) {
return
}
token := r.Header.Get("Authorization")
user := usertokens.Get(token)
if user == nil {
writeresult(w, codeError, nil, errInvalidToken.Error(), typeError)
return
}
ff, h, err := r.FormFile("avatar")
if err == nil {
defer ff.Close()
ct := h.Header.Get("Content-Type")
un := h.Filename
logrus.Infoln("[file.UploadHandler] receive avatar, username:", un, "& mime:", ct)
if !strings.HasPrefix(ct, "image/") {
writeresult(w, codeError, nil, "invalid mimetype", typeError)
return
}
if un != user.Name {
writeresult(w, codeError, nil, "username mismatch", typeError)
return
}
err = os.MkdirAll(global.FileFolder+strconv.Itoa(*user.ID), 0755)
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
buf := bytes.NewBuffer(make([]byte, 0, h.Size))
_, err := io.Copy(buf, ff)
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
data := buf.Bytes()
_, format, err := imgsz.DecodeSize(buf)
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
userf := global.FileFolder + strconv.Itoa(*user.ID) + "/"
err = os.MkdirAll(userf, 0755)
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
avf := userf + "avatar." + format
err = os.WriteFile(avf, data, 0644)
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
err = global.UserDB.UpdateUserInfo(*user.ID, "", avf[6:], "")
if err != nil {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
writeresult(w, codeSuccess, &upload{
Message: messageOk,
Code: codeSuccess,
URL: avf[6:],
}, messageOk, typeSuccess)
user.Avtr = avf[6:]
usertokens.Set(token, user)
logrus.Infoln("[file.UploadHandler] save avatar to", avf[6:])
return
}
if err != http.ErrMissingFile {
writeresult(w, codeError, nil, err.Error(), typeError)
return
}
}

View File

@@ -2,10 +2,16 @@ package api
import ( import (
"errors" "errors"
"strings"
"time"
"github.com/fumiama/paper-manager/backend/global" "github.com/fumiama/paper-manager/backend/global"
) )
const (
chineseDateLayout = "2006年01月02日15时04分05秒"
)
var ( var (
errInvalidToken = errors.New("invalid token") errInvalidToken = errors.New("invalid token")
) )
@@ -18,6 +24,9 @@ type getUserInfoResult struct {
Desc string `json:"desc"` Desc string `json:"desc"`
HomePath string `json:"homePath"` HomePath string `json:"homePath"`
Roles []role `json:"roles"` Roles []role `json:"roles"`
Date string `json:"date"`
Last string `json:"last"`
Contact string `json:"contact"`
} }
func getUserInfo(token string) (*getUserInfoResult, error) { func getUserInfo(token string) (*getUserInfoResult, error) {
@@ -25,6 +34,16 @@ func getUserInfo(token string) (*getUserInfoResult, error) {
if user == nil { if user == nil {
return nil, errInvalidToken return nil, errInvalidToken
} }
cont := user.Cont
if len(cont) > 7 {
sb := strings.Builder{}
sb.WriteString(cont[:3])
for i := 0; i < len(cont)-7; i++ {
sb.WriteByte('*')
}
sb.WriteString(cont[len(cont)-4:])
cont = sb.String()
}
return &getUserInfoResult{ return &getUserInfoResult{
UserID: *user.ID, UserID: *user.ID,
Username: user.Name, Username: user.Name,
@@ -37,6 +56,19 @@ func getUserInfo(token string) (*getUserInfoResult, error) {
} }
return "/dashboard/workbench" return "/dashboard/workbench"
}(), }(),
Roles: []role{{RoleName: user.Role.Nick(), Value: user.Role.String()}}, Roles: []role{{RoleName: user.Role.Nick(), Value: user.Role.String()}},
Date: time.Unix(user.Date, 0).Format(chineseDateLayout),
Last: time.Unix(user.Last, 0).Format(chineseDateLayout),
Contact: cont,
}, nil }, nil
} }
func logout(token string) error {
user := usertokens.Get(token)
if user == nil {
return errInvalidToken
}
loginstatus.Delete(user.Name)
usertokens.Delete(token)
return nil
}

View File

@@ -22,7 +22,7 @@ func init() {
func initdir(folder string) { func initdir(folder string) {
err := os.MkdirAll(folder, 0755) err := os.MkdirAll(folder, 0755)
if err != nil { if err != nil {
logrus.Errorln("[os.MkdirAll]\t", err) logrus.Errorln("[os.MkdirAll]", err)
os.Exit(line()) os.Exit(line())
} }
} }

View File

@@ -56,6 +56,7 @@ var (
ErrEmptyUserID = errors.New("empty user ID") ErrEmptyUserID = errors.New("empty user ID")
ErrEmptyContect = errors.New("empty contact") ErrEmptyContect = errors.New("empty contact")
ErrUsernameExists = errors.New("username exists") ErrUsernameExists = errors.New("username exists")
ErrInvalidName = errors.New("invalid name")
) )
func init() { func init() {
@@ -88,7 +89,7 @@ func init() {
Cont: "028-61830156", Cont: "028-61830156",
Desc: "日は山の端にかかりぬ", Desc: "日は山の端にかかりぬ",
}, "系统") }, "系统")
logrus.Warn("[global.user] 初次启动, 创建初始账户 fumiama 密码 123456") logrus.Warn("[user] 初次启动, 创建初始账户 fumiama 密码 123456")
} }
} }
@@ -121,6 +122,11 @@ func (u *UserDatabase) AddUser(user *User, opname string) error {
if u.IsNameExists(user.Name) { if u.IsNameExists(user.Name) {
return ErrUsernameExists return ErrUsernameExists
} }
for _, c := range user.Name {
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') {
return ErrInvalidName
}
}
user.Date = time.Now().Unix() user.Date = time.Now().Unix()
user.Last = user.Date user.Last = user.Date
_ = u.notifyUserAdded(opname, user.Name) _ = u.notifyUserAdded(opname, user.Name)
@@ -146,7 +152,7 @@ func (u *UserDatabase) UpdateUserInfo(id int, nick, avtr, desc string) error {
} }
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
return u.db.Insert(UserTableUser, user) return u.db.Insert(UserTableUser, &user)
} }
// UpdateUserRole ... // UpdateUserRole ...
@@ -161,7 +167,7 @@ func (u *UserDatabase) UpdateUserRole(id int, nr UserRole) error {
user.Role = nr user.Role = nr
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
return u.db.Insert(UserTableUser, user) return u.db.Insert(UserTableUser, &user)
} }
// UpdateUserPassword ... // UpdateUserPassword ...
@@ -178,7 +184,7 @@ func (u *UserDatabase) UpdateUserPassword(id int, npwd string) error {
_ = u.notifyPasswordChange(user.Name, npwd) _ = u.notifyPasswordChange(user.Name, npwd)
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
return u.db.Insert(UserTableUser, user) return u.db.Insert(UserTableUser, &user)
} }
// UpdateUserContact ... // UpdateUserContact ...
@@ -194,12 +200,18 @@ func (u *UserDatabase) UpdateUserContact(id int, ncont string) error {
_ = u.notifyContactChange(user.Name, ncont) _ = u.notifyContactChange(user.Name, ncont)
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
return u.db.Insert(UserTableUser, user) return u.db.Insert(UserTableUser, &user)
} }
// GetUserByName avoids sql injection by removing ; ' " = // GetUserByName avoids sql injection by removing ; ' " =
func (u *UserDatabase) GetUserByName(username string) (user User, err error) { func (u *UserDatabase) GetUserByName(username string) (user User, err error) {
username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username) username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username)
for _, c := range username {
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') {
err = ErrInvalidName
return
}
}
u.mu.RLock() u.mu.RLock()
err = u.db.Find(UserTableUser, &user, "WHERE Name='"+username+"'") err = u.db.Find(UserTableUser, &user, "WHERE Name='"+username+"'")
u.mu.RUnlock() u.mu.RUnlock()
@@ -209,6 +221,11 @@ func (u *UserDatabase) GetUserByName(username string) (user User, err error) {
// IsNameExists avoids sql injection by removing ; ' " = // IsNameExists avoids sql injection by removing ; ' " =
func (u *UserDatabase) IsNameExists(username string) bool { func (u *UserDatabase) IsNameExists(username string) bool {
username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username) username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username)
for _, c := range username {
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') {
return false
}
}
u.mu.RLock() u.mu.RLock()
defer u.mu.RUnlock() defer u.mu.RUnlock()
return u.db.CanFind(UserTableUser, "WHERE Name='"+username+"'") return u.db.CanFind(UserTableUser, "WHERE Name='"+username+"'")
@@ -265,6 +282,21 @@ func (u *UserDatabase) GetSuperIDs() (ids []int, err error) {
return return
} }
// IsUser checks if token is valid for a user
func (user *User) IsUser() bool {
return user.Role == RoleUser || user.Role == RoleFileManager || user.Role == RoleSuper
}
// IsFileManager checks if token is valid for a filemgr
func (user *User) IsFileManager() bool {
return user.Role == RoleFileManager || user.Role == RoleSuper
}
// IsSuper checks if token is valid for a super
func (user *User) IsSuper() bool {
return user.Role == RoleSuper
}
// Message is shown in the workbench // Message is shown in the workbench
type Message struct { type Message struct {
ID *int ID *int
@@ -282,7 +314,7 @@ func (u *UserDatabase) SendMessage(m *Message) error {
m.Date = time.Now().Unix() m.Date = time.Now().Unix()
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
return u.db.InsertUnique(UserTableMessage, &m) return u.db.InsertUnique(UserTableMessage, m)
} }
// NotifyRegister will send register notification to all supers // NotifyRegister will send register notification to all supers
@@ -290,6 +322,11 @@ func (u *UserDatabase) NotifyRegister(name, cont, pswd string) error {
if name == "" { if name == "" {
return ErrEmptyName return ErrEmptyName
} }
for _, c := range name {
if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') {
return ErrInvalidName
}
}
if pswd == "" { if pswd == "" {
return ErrEmptyPassword return ErrEmptyPassword
} }

View File

@@ -18,7 +18,7 @@ func IP(r *http.Request) string {
// IsMethod check if the method meets the requirement // IsMethod check if the method meets the requirement
// and response 405 Method Not Allowed if not matched // and response 405 Method Not Allowed if not matched
func IsMethod(m string, w http.ResponseWriter, r *http.Request) bool { func IsMethod(m string, w http.ResponseWriter, r *http.Request) bool {
logrus.Infoln("[utils.IsMethod]\t accept", IP(r), r.Method, r.URL) logrus.Infoln("[utils.IsMethod] accept", IP(r), r.Method, r.URL)
if r.Method != m { if r.Method != m {
http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed) http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed)
return false return false

View File

@@ -143,7 +143,7 @@ export default [
return resultSuccess(codeList) return resultSuccess(codeList)
}, },
}, },
{ /*{
url: '/api/logout', url: '/api/logout',
timeout: 200, timeout: 200,
method: 'get', method: 'get',
@@ -156,13 +156,13 @@ export default [
} }
return resultSuccess(undefined, { message: 'Token has been destroyed' }) return resultSuccess(undefined, { message: 'Token has been destroyed' })
}, },
}, },*/
{ /*{
url: '/api/testRetry', url: '/api/testRetry',
statusCode: 405, statusCode: 405,
method: 'get', method: 'get',
response: () => { response: () => {
return resultError('Error!') return resultError('Error!')
}, },
}, },*/
] as MockMethod[] ] as MockMethod[]

View File

@@ -66,6 +66,12 @@ export interface GetUserInfoModel {
avatar: string avatar: string
// 介绍 // 介绍
desc?: string desc?: string
// 创建日期
date: string
// 上次修改密码日期
last: string
// 电话
contact: string
} }
export interface GetLoginSaltModel { export interface GetLoginSaltModel {

View File

@@ -187,7 +187,7 @@
try { try {
setModalProps({ confirmLoading: true }) setModalProps({ confirmLoading: true })
const result = await uploadApi({ name: 'file', file: blob, filename }) const result = await uploadApi({ name: 'file', file: blob, filename })
emit('uploadSuccess', { source: previewSource.value, data: result.url }) emit('uploadSuccess', { source: previewSource.value, data: result.data.result.url })
closeModal() closeModal()
} finally { } finally {
setModalProps({ confirmLoading: false }) setModalProps({ confirmLoading: false })

View File

@@ -8,8 +8,8 @@
<div class="change-avatar"> <div class="change-avatar">
<div class="mb-2">头像</div> <div class="mb-2">头像</div>
<CropperAvatar <CropperAvatar
:uploadApi="uploadApi" :uploadApi="onUpload as any"
:value="avatar" :value="avatarRef"
btnText="更换头像" btnText="更换头像"
:btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }"
@change="updateAvatar" @change="updateAvatar"
@@ -23,7 +23,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Button, Row, Col } from 'ant-design-vue' import { Button, Row, Col } from 'ant-design-vue'
import { computed, defineComponent, onMounted } from 'vue' import { ref, defineComponent, onMounted } from 'vue'
import { BasicForm, useForm } from '/@/components/Form/index' import { BasicForm, useForm } from '/@/components/Form/index'
import { CollapseContainer } from '/@/components/Container' import { CollapseContainer } from '/@/components/Container'
import { CropperAvatar } from '/@/components/Cropper' import { CropperAvatar } from '/@/components/Cropper'
@@ -31,7 +31,6 @@
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
import headerImg from '/@/assets/images/header.jpg' import headerImg from '/@/assets/images/header.jpg'
import { accountInfoApi } from '/@/api/demo/account'
import { baseSetschemas } from './data' import { baseSetschemas } from './data'
import { useUserStore } from '/@/store/modules/user' import { useUserStore } from '/@/store/modules/user'
import { uploadApi } from '/@/api/sys/upload' import { uploadApi } from '/@/api/sys/upload'
@@ -48,6 +47,7 @@
setup() { setup() {
const { createMessage } = useMessage() const { createMessage } = useMessage()
const userStore = useUserStore() const userStore = useUserStore()
const { avatar } = userStore.getUserInfo
const [register, { setFieldsValue }] = useForm({ const [register, { setFieldsValue }] = useForm({
labelWidth: 120, labelWidth: 120,
@@ -56,27 +56,36 @@
}) })
onMounted(async () => { onMounted(async () => {
const data = await accountInfoApi() const data = userStore.getUserInfo
setFieldsValue(data) setFieldsValue(data)
}) })
const avatar = computed(() => { const avatarRef = ref(avatar || headerImg)
const { avatar } = userStore.getUserInfo
console.log(avatar)
return avatar || headerImg
})
function updateAvatar({ src, data }) { function updateAvatar({ src }) {
const userinfo = userStore.getUserInfo const userinfo = userStore.getUserInfo
userinfo.avatar = src userinfo.avatar = src
userStore.setUserInfo(userinfo) userStore.setUserInfo(userinfo)
console.log('data', data) }
async function onUpload(value: { file: Blob; name: string }) {
const data = userStore.getUserInfo
const result = await uploadApi(
{
name: 'avatar',
file: value.file,
filename: data.username,
},
() => {},
)
avatarRef.value = result.data.url
return result
} }
return { return {
avatar, avatarRef,
register, register,
uploadApi: uploadApi as any, onUpload,
updateAvatar, updateAvatar,
handleSubmit: () => { handleSubmit: () => {
createMessage.success('更新成功!') createMessage.success('更新成功!')

View File

@@ -23,14 +23,28 @@
import { List } from 'ant-design-vue' import { List } from 'ant-design-vue'
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { CollapseContainer } from '/@/components/Container/index' import { CollapseContainer } from '/@/components/Container/index'
import { useUserStore } from '/@/store/modules/user'
import { secureSettingList } from './data'
export default defineComponent({ export default defineComponent({
components: { CollapseContainer, List, ListItem: List.Item, ListItemMeta: List.Item.Meta }, components: { CollapseContainer, List, ListItem: List.Item, ListItemMeta: List.Item.Meta },
setup() { setup() {
const userStore = useUserStore()
const { last, contact } = userStore.getUserInfo
return { return {
list: secureSettingList, list: [
{
key: '1',
title: '账户密码',
description: '上次修改密码: ' + last,
extra: '修改',
},
{
key: '2',
title: '我的手机',
description: '已绑定手机: ' + contact,
extra: '修改',
},
],
} }
}, },
}) })

View File

@@ -1,14 +1,5 @@
import { FormSchema } from '/@/components/Form/index' import { FormSchema } from '/@/components/Form/index'
export interface ListItem {
key: string
title: string
description: string
extra?: string
avatar?: string
color?: string
}
// tab的list // tab的list
export const settingList = [ export const settingList = [
{ {
@@ -26,31 +17,15 @@ export const settingList = [
// 基础设置 form // 基础设置 form
export const baseSetschemas: FormSchema[] = [ export const baseSetschemas: FormSchema[] = [
{ {
field: 'name', field: 'realName',
component: 'Input', component: 'Input',
label: '昵称', label: '昵称',
colProps: { span: 18 }, colProps: { span: 18 },
}, },
{ {
field: 'introduction', field: 'desc',
component: 'InputTextArea', component: 'InputTextArea',
label: '个人简介', label: '个人简介',
colProps: { span: 18 }, colProps: { span: 18 },
}, },
] ]
// 安全设置 list
export const secureSettingList: ListItem[] = [
{
key: '1',
title: '账户密码',
description: '上次修改密码: 2022年1月1日0时0分0秒',
extra: '修改',
},
{
key: '2',
title: '我的手机',
description: '已绑定手机: 138****8293',
extra: '修改',
},
]

View File

@@ -30,6 +30,9 @@ export interface UserInfo {
desc?: string desc?: string
homePath?: string homePath?: string
roles: RoleInfo[] roles: RoleInfo[]
date: string
last: string
contact: string
} }
export interface BeforeMiniState { export interface BeforeMiniState {

1
go.mod
View File

@@ -7,6 +7,7 @@ require (
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b
github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e
github.com/fumiama/go-base16384 v1.6.4 github.com/fumiama/go-base16384 v1.6.4
github.com/fumiama/imgsz v0.0.2
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
) )

2
go.sum
View File

@@ -11,6 +11,8 @@ github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b h1:Zt3pFQditAdWTHCO
github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/fumiama/bigfft v0.0.0-20211011143303-6e0bfa3c836b/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/fumiama/go-base16384 v1.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o= github.com/fumiama/go-base16384 v1.6.4 h1:rYDRwD/th2cG4U7QLokpzmST1cCxZGXtHmolOUePt5o=
github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM= github.com/fumiama/go-base16384 v1.6.4/go.mod h1:OEn+947GV5gsbTAnyuUW/SrfxJYUdYupSIQXOuGOcXM=
github.com/fumiama/imgsz v0.0.2 h1:fAkC0FnIscdKOXwAxlyw3EUba5NzxZdSxGaq3Uyfxak=
github.com/fumiama/imgsz v0.0.2/go.mod h1:dR71mI3I2O5u6+PCpd47M9TZptzP+39tRBcbdIkoqM4=
github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k= github.com/fumiama/sqlite3 v1.20.0-with-win386 h1:ZR1AXGBEtkfq9GAXehOVcwn+aaCG8itrkgEsz4ggx5k=
github.com/fumiama/sqlite3 v1.20.0-with-win386/go.mod h1:Os58MHwYCcYZCy2PGChBrQtBAw5/LS1ZZOkfc+C/I7s= github.com/fumiama/sqlite3 v1.20.0-with-win386/go.mod h1:Os58MHwYCcYZCy2PGChBrQtBAw5/LS1ZZOkfc+C/I7s=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=

10
main.go
View File

@@ -10,7 +10,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/fumiama/paper-manager/backend/api" "github.com/fumiama/paper-manager/backend/api"
"github.com/fumiama/paper-manager/backend/file"
) )
func line() int { func line() int {
@@ -26,14 +25,15 @@ func main() {
flag.Parse() flag.Parse()
l, err := net.Listen("tcp", *addr) l, err := net.Listen("tcp", *addr)
if err != nil { if err != nil {
logrus.Errorln("[net.Listen]\t", err) logrus.Errorln("[net.Listen]", err)
os.Exit(line()) os.Exit(line())
} }
http.HandleFunc("/api/", api.Handler) http.HandleFunc("/api/", api.Handler)
http.HandleFunc("/file/", file.Handler) http.HandleFunc("/file/", api.FileHandler)
http.HandleFunc("/upload", api.UploadHandler)
logrus.Infoln("[http.Serve]\t start at", l.Addr()) logrus.Infoln("[http.Serve] start at", l.Addr())
logrus.Errorln("[http.Serve]\t", http.Serve(l, nil)) logrus.Errorln("[http.Serve]", http.Serve(l, nil))
os.Exit(line()) os.Exit(line())
} }