master
veypi 3 years ago
parent 33b1342f64
commit f9065abe55

@ -97,6 +97,8 @@ func (h *appHandler) Post() (interface{}, error) {
UUID: utils.RandSeq(16),
Name: data.Name,
Icon: data.Icon,
Host: "http://127.0.0.1",
UserRefreshUrl: "http://127.0.0.1?token=$token",
Creator: h.Payload.ID,
EnableRegister: false,
}

@ -48,7 +48,7 @@ func (h *handler) Get() (interface{}, error) {
if userID != 0 {
user := &models.User{}
user.ID = userID
return user, cfg.DB().Where(user).First(user).Error
return user, cfg.DB().Preload("Apps.App").Where(user).First(user).Error
} else {
username := h.Meta().Query("username")
if username != "" {
@ -107,7 +107,7 @@ func (h *handler) Post() (interface{}, error) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
h.User = new(models.User)
h.User.Icon = fmt.Sprintf("/media/icon/default/%04d.jpg", r.Intn(230))
h.User.Icon = fmt.Sprintf("/public/icon/default/%04d.jpg", r.Intn(230))
h.User.Nickname = userdata.Nickname
h.User.Phone = userdata.Phone
h.User.Username = userdata.Username

@ -63,14 +63,9 @@ var CFG = &struct {
DB: "one_auth",
},
ES: &config.Config{
URL: "http://127.0.0.1:9200",
Index: "",
Username: "",
Password: "",
Shards: 0,
Replicas: 0,
Sniff: nil,
Healthcheck: nil,
URL: "http://127.0.0.1:9200",
Username: "elastic",
Password: "123456",
},
}
@ -119,7 +114,14 @@ func ES() *elastic.Client {
func ConnectES() *elastic.Client {
var err error
es, err = elastic.NewClientFromConfig(CFG.ES)
//es, err = elastic.NewClientFromConfig(CFG.ES)
es, err = elastic.NewClient(
elastic.SetURL(CFG.ES.URL),
elastic.SetBasicAuth(CFG.ES.Username, CFG.ES.Password),
elastic.SetSniff(false),
elastic.SetHealthcheck(false),
elastic.SetErrorLog(log.ConsoleLogger()),
)
if err != nil {
log.Warn().Msgf("connect es failed: %s", err)
return nil

@ -7,7 +7,6 @@ import (
"github.com/veypi/OneAuth/oalib"
"github.com/veypi/OneBD"
"github.com/veypi/OneBD/rfc"
"github.com/veypi/utils/log"
"net/http"
"strconv"
)
@ -26,7 +25,6 @@ func appFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, moun
if h == "" {
h = m.Query("auth_token")
}
log.Warn().Msgf("|%s|%s|", r.Header.Get("auth_token"), m.Query("auth_token"))
var ok bool
ok, err = p.ParseToken(h, cfg.CFG.APPKey)
if !ok {
@ -49,6 +47,6 @@ func appFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, moun
actorID = strconv.Itoa(int(p.ID))
ownerID = uuid
mountPoint = uuid
prefix = cfg.CFG.FileUrlPrefix + "/app/" + uuid + "/"
prefix = uuid
return
}

@ -5,6 +5,7 @@ import (
"github.com/veypi/OneAuth/libs/fs"
"github.com/veypi/OneBD"
"github.com/veypi/OneBD/rfc"
"github.com/veypi/utils"
"github.com/veypi/utils/log"
)
@ -16,19 +17,32 @@ import (
**/
func Router(r OneBD.Router) {
// 用户私有文件
usrF := fs.FS{
RootDir: cfg.CFG.FireDir + "/usr/",
RootDir: utils.PathJoin(cfg.CFG.FireDir, "usr"),
UrlRoot: utils.PathJoin(cfg.CFG.FileUrlPrefix, "usr"),
MountFunc: userFileChecker,
}
log.Info().Msgf("start file server on %s", cfg.CFG.Host)
r.Set("/usr/", usrF.ServeHTTP, rfc.MethodAll)
r.Set("/usr/*", usrF.ServeHTTP, rfc.MethodAll)
// 应用存储文件
appF := fs.FS{
RootDir: cfg.CFG.FireDir + "/app/",
RootDir: utils.PathJoin(cfg.CFG.FireDir, "app"),
UrlRoot: utils.PathJoin(cfg.CFG.FileUrlPrefix, "app"),
MountFunc: appFileChecker,
DisabledAlert: true,
}
r.Set("/app/:uuid/", appF.ServeHTTP, rfc.MethodAll)
r.Set("/app/:uuid/*preifx", appF.ServeHTTP, rfc.MethodAll)
r.Set("/app/:uuid/*prefix", appF.ServeHTTP, rfc.MethodAll)
r.Set("/ursapp/:id/:uuid/*prefix", nil)
// 公共文件 读取无需权限
pubF := fs.FS{
RootDir: utils.PathJoin(cfg.CFG.FireDir, "public"),
UrlRoot: utils.PathJoin(cfg.CFG.FileUrlPrefix, "public"),
MountFunc: pubFileChecker,
DisabledAlert: true,
}
r.Set("/public/app/:uuid/*prefix", pubF.ServeHTTP, rfc.MethodAll)
r.Set("/public/*prefix", pubF.ServeHTTP, rfc.MethodAll)
}

@ -7,7 +7,6 @@ import (
"github.com/veypi/OneAuth/oalib"
"github.com/veypi/OneBD"
"github.com/veypi/OneBD/rfc"
"github.com/veypi/utils/log"
"net/http"
"strconv"
)
@ -18,15 +17,21 @@ import (
* @date: 2021-12-04 11:49
* @descriptionuser
**/
func appFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, mountPoint string, ownerID string, actorID string, err error) {
func pubFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, mountPoint string, ownerID string, actorID string, err error) {
m := w.(OneBD.Meta)
if r.Method == rfc.MethodGet {
mountPoint = ""
prefix = ""
ownerID = "public"
actorID = "public"
return
}
uuid := m.Params("uuid")
p := &oalib.PayLoad{}
h := r.Header.Get("auth_token")
if h == "" {
h = m.Query("auth_token")
}
log.Warn().Msgf("|%s|%s|", r.Header.Get("auth_token"), m.Query("auth_token"))
var ok bool
ok, err = p.ParseToken(h, cfg.CFG.APPKey)
if !ok {
@ -34,9 +39,6 @@ func appFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, moun
return
}
l := p.GetAuth(auth.APP, uuid)
if !l.CanRead() {
err = oerr.NoAuth
}
if !l.CanDelete() && r.Method == rfc.MethodDelete {
err = oerr.NoAuth
}
@ -48,7 +50,7 @@ func appFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, moun
}
actorID = strconv.Itoa(int(p.ID))
ownerID = uuid
mountPoint = uuid
prefix = cfg.CFG.FileUrlPrefix + "/app/" + uuid + "/"
mountPoint = "app/" + uuid
prefix = "app/" + uuid
return
}

@ -45,7 +45,7 @@ func userFileChecker(w http.ResponseWriter, r *http.Request) (prefix string, mou
actorID = strconv.Itoa(int(user.ID))
ownerID = actorID
mountPoint = actorID
prefix = cfg.CFG.FileUrlPrefix + "/usr/"
prefix = ""
return
}
return

@ -48,6 +48,7 @@ func JSONResponse(m OneBD.Meta, data interface{}, err error) {
log.Warn().Err(err).Msg("encode json data error")
return
}
m.Header().Set("Access-Control-Allow-Origin", "*")
_, _ = m.Write(p)
}

@ -67,7 +67,7 @@ func getFile(ctx context.Context, path string, h *webdav.Handler) (*models.File,
_, err = index.File.Index().Id(f.ID()).BodyJson(f).Do(ctx)
return f, err
} else if err != nil {
return nil, err
return f, err
}
err = json.Unmarshal(body.Source, f)
return f, err

@ -14,12 +14,19 @@ import (
"strings"
)
// MountFunc
// urlPrefix urlRoot+urlPrefix 为serverHttp 匹配的url前缀
// mountPoint fs.RootDir+mountPoint 为文件存储路径
type MountFunc = func(w http.ResponseWriter, r *http.Request) (urlPrefix string, mountPoint string, ownerID string, actorID string, err error)
type FS struct {
handlerCache map[string]*webdav.Handler
RootDir string
MountFunc MountFunc
DisabledAlert bool
handlerCache map[string]*webdav.Handler
RootDir string
UrlRoot string
MountFunc MountFunc
DisabledAlert bool
DisabledRecord bool
DisabledWrite bool
}
//go:embed netErr.png
@ -43,7 +50,7 @@ func (f *FS) mount(prefix, dir string) *webdav.Handler {
fs := webdav.Dir(p)
h := &webdav.Handler{
Prefix: prefix,
Prefix: utils.PathJoin(f.UrlRoot, prefix),
FileSystem: fs,
LockSystem: webdav.NewMemLS(),
Logger: func(r *http.Request, err error) {
@ -84,7 +91,9 @@ func (f *FS) ServeHTTP(w http.ResponseWriter, r *http.Request) {
FileError(w, http.StatusBadRequest)
return
}
f.setEvent(h)
if !f.DisabledRecord {
f.setEvent(h)
}
}
h.ServeHTTP(w, r)
}
@ -97,7 +106,8 @@ func (f *FS) setEvent(h *webdav.Handler) {
if err != nil {
return 0, err
}
return 0, addHistory(r, h, models.ActGet, tf.ID(), path)
err = addHistory(r, h, models.ActGet, tf.ID(), path)
return 0, err
}))
h.On(webdav.EventAfterUpdate, webdav.AfterUpdateFunc(func(r *http.Request, path string, size int64, md5Str string) (int, error) {
defer handlePanic()

@ -259,14 +259,15 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
return http.StatusInternalServerError, err
}
w.Header().Set("ETag", etag)
// Let ServeContent determine the Content-Type header.
http.ServeContent(w, r, reqPath, fi.ModTime(), f)
// 放在serveContent ctx 会被取消
if e := h.fire(EventAfterRead); e != nil {
_, err := e.(ReadFunc)(r, reqPath)
if err != nil {
h.Logger(r, err)
}
}
// Let ServeContent determine the Content-Type header.
http.ServeContent(w, r, reqPath, fi.ModTime(), f)
return 0, nil
}

@ -5,6 +5,8 @@ import (
"github.com/veypi/utils"
"github.com/veypi/utils/jwt"
"gorm.io/gorm"
"strconv"
"strings"
)
// User db user model
@ -21,11 +23,11 @@ type User struct {
Status string
Icon string
Roles []*Role `gorm:"many2many:UserRoles;"`
Apps []*App `gorm:"many2many:AppUsers;"`
Auths []*Auth `gorm:"foreignkey:UserID;references:ID"`
Used uint `gorm:"default:0"`
Space uint `gorm:"default:300"`
Roles []*Role `gorm:"many2many:UserRoles;"`
Apps []*AppUser `gorm:""`
Auths []*Auth `gorm:"foreignkey:UserID;references:ID"`
Used uint `gorm:"default:0"`
Space uint `gorm:"default:300"`
}
func (u *User) String() string {
@ -91,9 +93,10 @@ func (u *User) GetToken(uuid string, key []byte) (string, error) {
}
for _, a := range u.GetAuths() {
if uuid == a.AppUUID {
ruid := strings.ReplaceAll(a.RUID, "$id", strconv.Itoa(int(u.ID)))
payload.Auth = append(payload.Auth, &oalib.SimpleAuth{
RID: a.RID,
RUID: a.RUID,
RUID: ruid,
Level: a.Level,
})
}

@ -1,3 +0,0 @@
{
"recommendations": ["johnsoncodehk.volar"]
}

2793
oaf/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -13,36 +13,35 @@
"serve": "vite preview"
},
"dependencies": {
"@veypi/one-icon": "2.0.6",
"animate.css": "^4.1.1",
"axios": "^0.24.0",
"js-base64": "^3.7.2",
"seamless-scroll-polyfill": "^2.1.5",
"vue": "^3.2.16",
"vue-router": "^4.0.12",
"vuex": "^4.0.2",
"hot-patcher": "^0.5.0",
"fast-xml-parser": "^3.19.0",
"hot-patcher": "^0.5.0",
"js-base64": "^3.7.2",
"layerr": "^0.1.2",
"nested-property": "^4.0.0",
"path-posix": "^1.0.0",
"seamless-scroll-polyfill": "^2.1.5",
"url-join": "^4.0.1",
"url-parse": "^1.5.3",
"layerr": "^0.1.2",
"path-posix": "^1.0.0"
"vue": "^3.2.16",
"vue-router": "^4.0.12",
"vuex": "^4.0.2"
},
"devDependencies": {
"@veypi/oaer": "file:src/oaer",
"@veypi/one-icon": "2.0.6",
"@types/node": "^16.11.12",
"@vitejs/plugin-vue": "^1.9.3",
"autoprefixer": "^9.8.8",
"base-64": "^1.0.0",
"less": "^4.1.2",
"md5": "^2.3.0",
"naive-ui": "^2.19.11",
"autoprefixer": "^9.8.8",
"postcss": "^7.0.39",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@2.1.0",
"typescript": "^4.4.3",
"vfonts": "^0.1.0",
"vite": "^2.6.4",
"base-64": "^1.0.0",
"md5": "^2.3.0",
"vue-tsc": "^0.3.0"
}
}

@ -30,6 +30,7 @@ function baseRequests(url: string, method: any = 'GET', query: any, data: any, s
}).then((res: any) => {
if ('auth_token' in res.headers) {
localStorage.auth_token = res.headers.auth_token
store.commit('user/refreshToken', localStorage.auth_token)
}
if ('redirect_url' in res.headers) {
window.location.href = res.headers.redirect_url

@ -72,23 +72,15 @@
import {Theme, IsDark, ChangeTheme} from '@/theme'
import {zhCN, dateZhCN} from 'naive-ui'
import fullscreen from './fullscreen'
import avatar from './avatar'
import {onMounted, ref} from 'vue'
import {ref} from 'vue'
import {useStore} from '@/store'
import {useRouter} from 'vue-router'
import util from '@/libs/util'
import {OAer, Cfg} from '@/oaer'
Cfg.token.value = util.getToken()
let store = useStore()
let router = useRouter()
let isFullScreen = ref(false)
onMounted(() => {
})
onMounted(() => {
})
</script>
<style scoped>

@ -1,15 +1,13 @@
<template>
<BaseFrame v-model="shown" :is-dark="isDark">
<template #title>
{{self.Name}}
{{ self.Name }}
</template>
<slot>
<div class="flex justify-center items-center">
<n-avatar style="--color: none" :src="Cfg.host.value + usr.Icon"
round></n-avatar>
</div>
</slot>
<template v-slot:main>
<div class="flex justify-center items-center">
<n-avatar style="--color: none" :src="Cfg.host.value + usr.Icon"
round></n-avatar>
</div>
<template #main>
<div style="height: 100%">
<div style="height: calc(100% - 50px)">
<div class="w-full px-3">
@ -60,6 +58,7 @@ import {decode} from 'js-base64'
import {api, Cfg} from './api'
import evt from './evt'
import {modelsApp, modelsUser} from './models'
console.log('init oaer')
let shown = ref(false)
let emits = defineEmits<{
@ -72,6 +71,7 @@ let props = withDefaults(defineProps<{
isDark: false,
})
onMounted(() => {
console.log('mount')
fetchUserData()
})
@ -81,11 +81,13 @@ let self = ref<modelsApp>({} as modelsApp)
let token = computed(() => Cfg.token.value)
watch(token, () => {
console.log('sync token')
fetchUserData()
})
function fetchUserData() {
let token = Cfg.token.value?.split('.')
console.log(token)
if (!token || token.length !== 3) {
return false
}
@ -93,7 +95,6 @@ function fetchUserData() {
if (data.ID > 0) {
api.user.get(data.ID).Start(e => {
usr.value = e
console.log(e)
ofApps.value = []
for (let v of e.Apps) {
if (v.Status === 'ok') {
@ -114,7 +115,6 @@ function fetchUserData() {
}
evt.on('logout', () => {
emits('logout')
})

@ -6,6 +6,7 @@ import {State} from './index'
import router from "@/router";
import {Auths, NewAuths} from '@/auth'
import {modelsSimpleAuth, modelsUser} from '@/models'
import {Cfg} from '@/oaer'
export interface UserState {
id: number
@ -31,6 +32,9 @@ export const User: Module<UserState, State> = {
setAuth(state: UserState, data: modelsSimpleAuth[]) {
state.auth = NewAuths(data)
},
refreshToken(state: UserState, data: string) {
Cfg.token.value = util.getToken()
},
logout(state: UserState) {
state.ready = false
localStorage.removeItem('auth_token')

@ -67,7 +67,6 @@ export function ChangeTheme() {
}
}
console.log(OsThemeRef.value)
if (OsThemeRef.value === 'dark') {
change('dark')
}

@ -82,10 +82,8 @@ function login() {
}
function redirect(url?: string) {
console.log(util.checkLogin())
if (uuid.value && uuid.value !== store.state.oauuid) {
api.app.get(uuid.value as string).Start((app: modelsApp) => {
console.log(app.UserRefreshUrl)
api.token(uuid.value as string).get().Start(e => {
if (!url) {
url = app.UserRefreshUrl
@ -97,7 +95,6 @@ function redirect(url?: string) {
}, e => {
})
} else if (util.checkLogin()) {
console.log(url)
if (url) {
router.push(url)
} else {

@ -25,5 +25,8 @@
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"exclude": [
"src/libs/webdav"
]
}

@ -6,10 +6,12 @@ import * as path from 'path'
export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
'@': path.resolve(__dirname, 'src'),
},
},
plugins: [vue()],
plugins: [
vue()
],
server: {
host: '0.0.0.0',
// host: '127.0.0.1',
@ -18,19 +20,19 @@ export default defineConfig({
'/api': {
target: 'http://127.0.0.1:4001/',
changeOrigin: true,
ws: true
ws: true,
},
'/file': {
target: 'http://127.0.0.1:4001/',
changeOrigin: true,
ws: true
ws: true,
},
'/media': {
target: 'http://127.0.0.1:4001/',
changeOrigin: true,
ws: true
}
}
ws: true,
},
},
},
build: {
outDir: '../sub/static/',
@ -40,8 +42,8 @@ export default defineConfig({
// 重点在这里哦
entryFileNames: `static/[name].[hash].js`,
chunkFileNames: `static/[name].[hash].js`,
assetFileNames: `static/[name].[hash].[ext]`
}
}
}
assetFileNames: `static/[name].[hash].[ext]`,
},
},
},
})

File diff suppressed because it is too large Load Diff

@ -14,10 +14,10 @@
s.parentNode.insertBefore(hm, s);
})();
</script>
<script type="module" crossorigin src="/static/index.21e34d10.js"></script>
<link rel="modulepreload" href="/static/vendor.e7207b5f.js">
<script type="module" crossorigin src="/static/index.0c43f182.js"></script>
<link rel="modulepreload" href="/static/vendor.57758be5.js">
<link rel="stylesheet" href="/static/vendor.7d59d594.css">
<link rel="stylesheet" href="/static/index.9f48f778.css">
<link rel="stylesheet" href="/static/index.8c91f339.css">
</head>
<body>
<div id="app"></div>

Loading…
Cancel
Save