fix: fs auth bug

v3
veypi 3 weeks ago
parent 23b85c1495
commit 7e1235cb28

@ -44,18 +44,17 @@ func NewAppFs(prefix string) func(http.ResponseWriter, *http.Request) {
root = "/" + strings.Join(dirs[1:], "/") root = "/" + strings.Join(dirs[1:], "/")
} }
if root == "/" { if root == "/" {
if !utils.FileExists(tmp + "/" + aid) { // if !utils.FileExists(tmp + "/" + aid) {
os.MkdirAll(tmp+"/"+aid, 0744) // os.MkdirAll(tmp+"/"+aid, 0744)
} // }
} }
logv.Warn().Msgf("aid: %v, root: %v", aid, root)
if aid == "" { if aid == "" {
return "", errs.AuthNoPerm return "", errs.AuthNoPerm
} }
if root == "/pub" || strings.HasPrefix(root, "/pub/") { if root == "/pub" || strings.HasPrefix(root, "/pub/") {
switch r.Method { switch r.Method {
case "OPTIONS", "GET", "HEAD", "POST": case "OPTIONS", "GET", "HEAD", "POST":
return dir, nil return "", nil
default: default:
} }
} }
@ -75,8 +74,8 @@ func NewAppFs(prefix string) func(http.ResponseWriter, *http.Request) {
if err != nil { if err != nil {
return "", err return "", err
} }
if payload.Access.CheckPrefix("app", aid, handlerLevle) { if payload.Access.Check("app", aid, handlerLevle) {
return "/" + payload.UID + dir, nil return "", nil
} }
return "", errs.AuthNoPerm return "", errs.AuthNoPerm
} }

@ -62,7 +62,11 @@ func getToken(r *http.Request) (*auth.Claims, error) {
authHeader := r.Header.Get("Authorization") authHeader := r.Header.Get("Authorization")
token := "" token := ""
if authHeader != "" { if authHeader != "" {
if strings.HasPrefix(authHeader, "Basic ") { typ := ""
if tags := strings.Split(authHeader, " "); len(tags) > 1 {
typ = strings.ToLower(tags[0])
}
if typ == "basic" {
decodedAuth, err := base64.StdEncoding.DecodeString(authHeader[6:]) decodedAuth, err := base64.StdEncoding.DecodeString(authHeader[6:])
if err != nil { if err != nil {
return nil, errs.AuthInvalid return nil, errs.AuthInvalid
@ -76,11 +80,8 @@ func getToken(r *http.Request) (*auth.Claims, error) {
username = strings.TrimSuffix(username, "\n") username = strings.TrimSuffix(username, "\n")
username = strings.TrimSuffix(username, ":") username = strings.TrimSuffix(username, ":")
token = strings.TrimPrefix(password, "\n") token = strings.TrimPrefix(password, "\n")
logv.Warn().Msgf("username: %s, password: %s", username, token) } else if typ == "bearer" {
token = authHeader[7:]
}
if strings.HasPrefix(authHeader, "Bearer ") {
token = strings.TrimPrefix(authHeader, "Bearer ")
} }
} else { } else {
acookie, err := r.Cookie("fstoken") acookie, err := r.Cookie("fstoken")

@ -96,7 +96,7 @@ func (d Dir) OpenFile(ctx context.Context, name string, flag int, perm os.FileMo
if err != nil { if err != nil {
return nil, err return nil, err
} }
return d.OpenFile(ctx, name, flag, perm) return os.OpenFile(name, flag, perm)
} }
return nil, err return nil, err
} }

@ -37,16 +37,13 @@ class davWraper {
this.prefix = this.prefix.slice(0, -1) this.prefix = this.prefix.slice(0, -1)
} }
} }
set(k: 'host' | 'token', value: string) { set(k: 'host' | 'token' | 'prefix', value: string) {
if (value !== this[k]) { if (value !== this[k]) {
this[k] = value this[k] = value
if (k === 'token') { this.client = webdav.createClient(this.host + this.prefix)
this.client.setHeaders({ this.client.setHeaders({
authorization: "bearer " + value authorization: "bearer " + this.token
}) })
} else if (k === 'host') {
this.client = webdav.createClient(this.host + this.prefix)
}
} }
} }
putFileContents(filename: string, data: string | webdav.BufferLike, options?: webdav.PutFileContentsOptions) { putFileContents(filename: string, data: string | webdav.BufferLike, options?: webdav.PutFileContentsOptions) {
@ -78,6 +75,7 @@ class davWraper {
let retries = 0; let retries = 0;
function attempt(): Promise<T> { function attempt(): Promise<T> {
return fn().catch(error => { return fn().catch(error => {
console.log(error.status)
if (retries < 3) { if (retries < 3) {
retries++; retries++;
console.log(`Attempt ${retries} failed, retrying after 1 second...`); console.log(`Attempt ${retries} failed, retrying after 1 second...`);
@ -94,7 +92,7 @@ class davWraper {
let token = logic.token.oa.raw() let token = logic.token.oa.raw()
const user = new davWraper(logic.Host(), '/fs/u/', token) const user = new davWraper(logic.Host(), '/fs/u/', token)
const app = new davWraper(logic.Host(), '/fs/a/', token) const app = new davWraper(logic.Host(), '/fs/a/' + logic.oa_id, token)
export const set_host = (h: string) => { export const set_host = (h: string) => {
@ -107,6 +105,7 @@ const sync = () => {
// console.warn('sync oafs token: ' + t) // console.warn('sync oafs token: ' + t)
user.set('token', t) user.set('token', t)
app.set('token', t) app.set('token', t)
app.set('prefix', '/fs/a/' + logic.app_id)
} }
} }
proxy.Listen(() => { proxy.Listen(() => {

@ -178,6 +178,7 @@ bus.on('logout', () => {
// load token from localStorage // load token from localStorage
logic.token.refresh = new Token('refresh') logic.token.refresh = new Token('refresh')
logic.app_id = logic.token.refresh.aid || ''
logic.token.oa = new Token('oa') logic.token.oa = new Token('oa')
logic.token.app = new Token('app') logic.token.app = new Token('app')

@ -50,7 +50,7 @@ export const token = {
} }
// 请求拦截 // 请求拦截
const beforeRequest = (config: any) => { const beforeRequest = (config: any) => {
config.retryTimes = 3 config.retryTimes = config.retryTimes || 3
// NOTE 添加自定义头部 // NOTE 添加自定义头部
token.value && (config.headers.Authorization = `Bearer ${token.value}`) token.value && (config.headers.Authorization = `Bearer ${token.value}`)
return config return config
@ -76,24 +76,25 @@ const responseSuccess = (client: AxiosInstance) => {
const responseFailed = (client: AxiosInstance) => { const responseFailed = (client: AxiosInstance) => {
return (error: AxiosError) => { return (error: AxiosError) => {
const { response } = error const { response } = error
const config = response?.config
const data = response?.data || {} as any const data = response?.data || {} as any
if (!window.navigator.onLine) { if (!window.navigator.onLine) {
alert('没有网络') alert('没有网络')
return Promise.reject(new Error('请检查网络连接')) return Promise.reject(new Error('请检查网络连接'))
} }
let needRetry = true // @ts-ignore
let needRetry = config?.needRetry !== false
if (response?.status == 404) { if (response?.status == 404) {
needRetry = false needRetry = false
} else if (response?.status == 401) { } else if (response?.status == 401 && needRetry) {
needRetry = false needRetry = false
// AuthNotFound = New(40100, "auth not found") // AuthNotFound = New(40100, "auth not found")
// AuthExpired = New(40102, "auth expired") // AuthExpired = New(40102, "auth expired")
if (data.code === 40102 || data.code === 40100) { if (data.code === 40102 || data.code === 40100) {
token.value = '' token.value = ''
return token.update().then((e) => { return token.update().then(() => {
console.log('token updated: ' + e) return requestRetry(client)(200, response!)
return requestRetry(client)(500, response!)
}) })
} }
} else if (response?.status == 500) { } else if (response?.status == 500) {
@ -143,6 +144,7 @@ interface data {
query?: any query?: any
form?: any form?: any
header?: any header?: any
config?: Object
} }
@ -159,6 +161,9 @@ function transData(d: data) {
if (d.header) { if (d.header) {
opts.headers = Object.assign(opts.headers, d.header) opts.headers = Object.assign(opts.headers, d.header)
} }
if (d.config) {
opts = Object.assign(opts, d.config)
}
return opts return opts
} }

@ -36,14 +36,13 @@
<div class="text-h6">{{ $t('p.index.create') }} </div> <div class="text-h6">{{ $t('p.index.create') }} </div>
</template> </template>
<div class="p-4"> <div class="p-4">
<Uploader @success="temp_app.icon = $event" dir="app_icon"> <Uploader @success="temp_app.icon = $event" dir="/pub/icon/">
<!-- <img alt="LOGO" class="rounded-full w-16 h-16 mx-auto my-4" :src="temp_app.icon"> --> <!-- <img alt="LOGO" class="rounded-full w-16 h-16 mx-auto my-4" :src="temp_app.icon"> -->
<div alt="LOGO" class="divimg rounded-full w-16 h-16 mx-auto" :style="`--bgurl:url('${temp_app.icon}')`"> <div alt="LOGO" class="divimg rounded-full w-16 h-16 mx-auto" :style="`--bgurl:url('${temp_app.icon}')`">
</div> </div>
</Uploader> </Uploader>
<Vinput class="mt-4" v-model="temp_app.name" :validate="/^\w{2,}$/" :label="$t('c.appname')" type="text"> <Vinput class="mt-4" v-model="temp_app.name" :validate="/^\w{2,}$/" :label="$t('c.appname')" type="text">
</Vinput> </Vinput>
{{ temp_app.typ }}
<Vinput class='mt-12' v-model="temp_app.typ" type="radio" <Vinput class='mt-12' v-model="temp_app.typ" type="radio"
:options="{ 'public': $t('atyp.public'), 'apply': $t('atyp.apply'), 'private': $t('atyp.private') }" :options="{ 'public': $t('atyp.public'), 'apply': $t('atyp.apply'), 'private': $t('atyp.private') }"
:validate="/^\w{2,}$/"> :validate="/^\w{2,}$/">
@ -57,33 +56,6 @@
</template> </template>
</UCard> </UCard>
</UModal> </UModal>
<!-- <q-dialog :square="false" v-model="new_flag"> -->
<!-- <q-card class="w-4/5 md:w-96 rounded-2xl"> -->
<!-- <q-card-section> -->
<!-- </q-card-section> -->
<!-- <q-separator></q-separator> -->
<!-- <q-card-section> -->
<!-- <q-form @submit="create_new"> -->
<!-- <q-input label="应用名" v-model="temp_app.name" :rules="rules.name"></q-input> -->
<!-- <div class="flex justify-center my-4 items-center" label='icon'> -->
<!-- <uploader @success="temp_app.icon = $event" dir="app_icon"> -->
<!-- <q-avatar> -->
<!-- <img :src="temp_app.icon"> -->
<!-- </q-avatar> -->
<!-- </uploader> -->
<!-- <q-icon class="ml-2" size="1rem" name='autorenew' @click="temp_app.icon = rand_icon()"></q-icon> -->
<!-- </div> -->
<!-- <q-separator></q-separator> -->
<!-- <div class="flex justify-end mt-8"> -->
<!-- <q-btn class="mx-3" @click="new_flag = false">取消</q-btn> -->
<!-- <q-btn type="submit">创建</q-btn> -->
<!-- </div> -->
<!-- </q-form> -->
<!-- </q-card-section> -->
<!-- </q-card> -->
<!-- </q-dialog> -->
</div> </div>
</template> </template>

Loading…
Cancel
Save