veypi 2 months ago
parent dcce188e7a
commit fe77d154a0

@ -66,7 +66,7 @@ func tokenPost(x *rest.X) (any, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if oldClaim.AID == *opts.AppID { if oldClaim.AID == aid {
// refresh token // refresh token
claim.AID = oldClaim.AID claim.AID = oldClaim.AID
claim.UID = oldClaim.UID claim.UID = oldClaim.UID
@ -95,7 +95,7 @@ func tokenPost(x *rest.X) (any, error) {
key := logv.AssertFuncErr(hex.DecodeString(user.Code)) key := logv.AssertFuncErr(hex.DecodeString(user.Code))
de, err := utils.AesDecrypt([]byte(code), key, salt) de, err := utils.AesDecrypt([]byte(code), key, salt)
if err != nil || de != user.ID { if err != nil || de != user.ID {
return nil, errs.AuthInvalid return nil, errs.AuthFailed
} }
data.UserID = opts.UserID data.UserID = opts.UserID
data.AppID = aid data.AppID = aid
@ -110,6 +110,7 @@ func tokenPost(x *rest.X) (any, error) {
if opts.Device != nil { if opts.Device != nil {
data.Device = *opts.Device data.Device = *opts.Device
} }
data.Ip = x.GetRemoteIp()
data.ExpiredAt = time.Now().Add(time.Hour) data.ExpiredAt = time.Now().Add(time.Hour)
logv.AssertError(cfg.DB().Create(data).Error) logv.AssertError(cfg.DB().Create(data).Error)
claim.ID = data.ID claim.ID = data.ID

@ -9,6 +9,7 @@ package auth
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"oa/cfg" "oa/cfg"
"oa/errs" "oa/errs"
@ -39,6 +40,9 @@ func ParseJwt(tokenString string) (*Claims, error) {
} }
return []byte(cfg.Config.Key), nil return []byte(cfg.Config.Key), nil
}) })
if errors.Is(err, jwt.ErrTokenExpired) {
return nil, errs.AuthExpired
}
if err != nil || !token.Valid { if err != nil || !token.Valid {
return nil, errs.AuthInvalid return nil, errs.AuthInvalid
@ -78,7 +82,7 @@ func Check(target string, pid string, l AuthLevel) func(x *rest.X) error {
tid = x.Params.GetStr(pid) tid = x.Params.GetStr(pid)
} }
if !claims.Access.Check(target, tid, l) { if !claims.Access.Check(target, tid, l) {
return errs.AuthFailed return errs.AuthNoPerm
} }
return nil return nil
} }

@ -14,4 +14,5 @@ type Token struct {
ExpiredAt time.Time `json:"expired_at" methods:"*post,*patch" parse:"json"` ExpiredAt time.Time `json:"expired_at" methods:"*post,*patch" parse:"json"`
OverPerm string `json:"over_perm" methods:"*post,*patch" parse:"json"` OverPerm string `json:"over_perm" methods:"*post,*patch" parse:"json"`
Device string `json:"device" methods:"*post" parse:"json"` Device string `json:"device" methods:"*post" parse:"json"`
Ip string `json:"ip"`
} }

@ -7,10 +7,10 @@
import webapi from "./webapi" import webapi from "./webapi"
import * as models from "./models" import * as models from "./models"
export interface ListOpts { export interface ListOpts {
app_id: String app_id: string
user_id?: String user_id?: string
role_id?: String role_id?: string
name?: String name?: string
} }
export interface ListQuery { export interface ListQuery {
created_at?: Date created_at?: Date
@ -21,12 +21,12 @@ export function List(json: ListOpts, query: ListQuery) {
} }
export interface PostOpts { export interface PostOpts {
app_id: String app_id: string
user_id?: String user_id?: string
role_id?: String role_id?: string
name: String name: string
t_id: String t_id: string
level: Number level: number
} }
export function Post(json: PostOpts) { export function Post(json: PostOpts) {
return webapi.Post<models.Access>(`/access`, { json }) return webapi.Post<models.Access>(`/access`, { json })

@ -7,46 +7,46 @@
import webapi from "./webapi" import webapi from "./webapi"
import * as models from "./models" import * as models from "./models"
export interface GetOpts { export interface GetOpts {
name: String name: string
} }
export function Get(app_id: String, json: GetOpts) { export function Get(app_id: string, json: GetOpts) {
return webapi.Get<models.App>(`/app/${app_id}`, { json }) return webapi.Get<models.App>(`/app/${app_id}`, { json })
} }
export function AppUserDelete(app_user_id: String, app_id: String) { export function AppUserDelete(app_user_id: string, app_id: string) {
return webapi.Delete<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { }) return webapi.Delete<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { })
} }
export function ResourcePatch(app_id: String) { export function ResourcePatch(app_id: string) {
return webapi.Patch<models.Resource>(`/app/${app_id}/resource`, { }) return webapi.Patch<models.Resource>(`/app/${app_id}/resource`, { })
} }
export interface PatchOpts { export interface PatchOpts {
name?: String name?: string
icon?: String icon?: string
des?: String des?: string
participate?: String participate?: string
init_role_id?: String init_role_id?: string
} }
export function Patch(app_id: String, json: PatchOpts) { export function Patch(app_id: string, json: PatchOpts) {
return webapi.Patch<models.App>(`/app/${app_id}`, { json }) return webapi.Patch<models.App>(`/app/${app_id}`, { json })
} }
export interface PostOpts { export interface PostOpts {
name: String name: string
icon: String icon: string
des: String des: string
participate: String participate: string
} }
export function Post(json: PostOpts) { export function Post(json: PostOpts) {
return webapi.Post<models.App>(`/app`, { json }) return webapi.Post<models.App>(`/app`, { json })
} }
export interface AppUserListOpts { export interface AppUserListOpts {
user_id?: String user_id?: string
status?: String status?: string
} }
export function AppUserList(app_id: String, json: AppUserListOpts) { export function AppUserList(app_id: string, json: AppUserListOpts) {
return webapi.Get<models.AppUser>(`/app/${app_id}/app_user`, { json }) return webapi.Get<models.AppUser>(`/app/${app_id}/app_user`, { json })
} }
@ -54,59 +54,59 @@ export interface ResourceListQuery {
created_at?: Date created_at?: Date
updated_at?: Date updated_at?: Date
} }
export function ResourceList(app_id: String, query: ResourceListQuery) { export function ResourceList(app_id: string, query: ResourceListQuery) {
return webapi.Get<models.Resource>(`/app/${app_id}/resource`, { query }) return webapi.Get<models.Resource>(`/app/${app_id}/resource`, { query })
} }
export interface ResourcePostOpts { export interface ResourcePostOpts {
name: String name: string
des: String des: string
} }
export function ResourcePost(app_id: String, json: ResourcePostOpts) { export function ResourcePost(app_id: string, json: ResourcePostOpts) {
return webapi.Post<models.Resource>(`/app/${app_id}/resource`, { json }) return webapi.Post<models.Resource>(`/app/${app_id}/resource`, { json })
} }
export function Delete(app_id: String) { export function Delete(app_id: string) {
return webapi.Delete<models.App>(`/app/${app_id}`, { }) return webapi.Delete<models.App>(`/app/${app_id}`, { })
} }
export interface ListOpts { export interface ListOpts {
name?: String name?: string
} }
export function List(json: ListOpts) { export function List(json: ListOpts) {
return webapi.Get<models.App>(`/app`, { json }) return webapi.Get<models.App>(`/app`, { json })
} }
export interface AppUserGetOpts { export interface AppUserGetOpts {
user_id: String user_id: string
} }
export function AppUserGet(app_user_id: String, app_id: String, json: AppUserGetOpts) { export function AppUserGet(app_user_id: string, app_id: string, json: AppUserGetOpts) {
return webapi.Get<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { json }) return webapi.Get<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { json })
} }
export function ResourceGet(app_id: String) { export function ResourceGet(app_id: string) {
return webapi.Get<models.Resource>(`/app/${app_id}/resource`, { }) return webapi.Get<models.Resource>(`/app/${app_id}/resource`, { })
} }
export interface AppUserPatchOpts { export interface AppUserPatchOpts {
status?: String status?: string
} }
export function AppUserPatch(app_user_id: String, app_id: String, json: AppUserPatchOpts) { export function AppUserPatch(app_user_id: string, app_id: string, json: AppUserPatchOpts) {
return webapi.Patch<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { json }) return webapi.Patch<models.AppUser>(`/app/${app_id}/app_user/${app_user_id}`, { json })
} }
export interface AppUserPostOpts { export interface AppUserPostOpts {
status: String status: string
user_id: String user_id: string
} }
export function AppUserPost(app_id: String, json: AppUserPostOpts) { export function AppUserPost(app_id: string, json: AppUserPostOpts) {
return webapi.Post<models.AppUser>(`/app/${app_id}/app_user`, { json }) return webapi.Post<models.AppUser>(`/app/${app_id}/app_user`, { json })
} }
export interface ResourceDeleteOpts { export interface ResourceDeleteOpts {
name: String name: string
} }
export function ResourceDelete(app_id: String, json: ResourceDeleteOpts) { export function ResourceDelete(app_id: string, json: ResourceDeleteOpts) {
return webapi.Delete<models.Resource>(`/app/${app_id}/resource`, { json }) return webapi.Delete<models.Resource>(`/app/${app_id}/resource`, { json })
} }

@ -1,44 +1,44 @@
export interface Access { export interface Access {
app_id: String app_id: string
app?: App app?: App
user_id?: String user_id?: string
user?: User user?: User
role_id?: String role_id?: string
role?: Role role?: Role
name: String name: string
t_id: String t_id: string
level: Number level: number
} }
export interface App { export interface App {
name: String name: string
icon: String icon: string
des: String des: string
participate: String participate: string
init_role_id?: String init_role_id?: string
init_role?: Role init_role?: Role
init_url: String init_url: string
user_count: Number user_count: number
key: String key: string
} }
export interface AppUser { export interface AppUser {
app_id: String app_id: string
app?: App app?: App
user_id: String user_id: string
user?: User user?: User
status: String status: string
} }
export interface Resource { export interface Resource {
app_id: String app_id: string
app?: App app?: App
name: String name: string
des: String des: string
} }
export interface Role { export interface Role {
name: String name: string
des: String des: string
app_id: String app_id: string
app?: App app?: App
user_count: Number user_count: number
access: any access: any
} }
export interface Testb { export interface Testb {
@ -50,30 +50,30 @@ export interface Test {
name: String name: String
} }
export interface Token { export interface Token {
user_id: String user_id: string
user?: User user?: User
app_id: String app_id: string
app?: App app?: App
expired_at: Date expired_at: Date
over_perm: String over_perm: string
device: String device: string
} }
export interface User { export interface User {
username: String username: string
nickname: String nickname: string
icon: String icon: string
email: String email: string
phone: String phone: string
status: Number status: number
salt: String salt: string
code: String code: string
} }
export interface UserRole { export interface UserRole {
user_id: String user_id: string
user?: User user?: User
role_id: String role_id: string
role?: Role role?: Role
app_id: String app_id: string
app?: App app?: App
status: String status: string
} }

@ -7,33 +7,33 @@
import webapi from "./webapi" import webapi from "./webapi"
import * as models from "./models" import * as models from "./models"
export interface ListOpts { export interface ListOpts {
name?: String name?: string
} }
export function List(json: ListOpts) { export function List(json: ListOpts) {
return webapi.Get<models.Role>(`/role`, { json }) return webapi.Get<models.Role>(`/role`, { json })
} }
export function Get(role_id: String) { export function Get(role_id: string) {
return webapi.Get<models.Role>(`/role/${role_id}`, { }) return webapi.Get<models.Role>(`/role/${role_id}`, { })
} }
export interface PatchOpts { export interface PatchOpts {
name?: String name?: string
des?: String des?: string
app_id?: String app_id?: string
} }
export function Patch(role_id: String, json: PatchOpts) { export function Patch(role_id: string, json: PatchOpts) {
return webapi.Patch<models.Role>(`/role/${role_id}`, { json }) return webapi.Patch<models.Role>(`/role/${role_id}`, { json })
} }
export function Delete(role_id: String) { export function Delete(role_id: string) {
return webapi.Delete<models.Role>(`/role/${role_id}`, { }) return webapi.Delete<models.Role>(`/role/${role_id}`, { })
} }
export interface PostOpts { export interface PostOpts {
name: String name: string
des: String des: string
app_id: String app_id: string
} }
export function Post(json: PostOpts) { export function Post(json: PostOpts) {
return webapi.Post<models.Role>(`/role`, { json }) return webapi.Post<models.Role>(`/role`, { json })

@ -6,51 +6,52 @@
import webapi from "./webapi" import webapi from "./webapi"
import * as models from "./models" import * as models from "./models"
export function Delete(token_id: String) { export function Delete(token_id: string) {
return webapi.Delete<models.Token>(`/token/${token_id}`, {}) return webapi.Delete<models.Token>(`/token/${token_id}`, {})
} }
export interface ListOpts { export interface ListOpts {
user_id: String user_id: string
app_id: String app_id: string
} }
export function List(json: ListOpts) { export function List(json: ListOpts) {
return webapi.Get<models.Token>(`/token`, { json }) return webapi.Get<models.Token>(`/token`, { json })
} }
export interface TokenSaltOpts { export interface TokenSaltOpts {
username: String username: string
typ?: String typ?: string
} }
// keep // keep
export function TokenSalt(json: TokenSaltOpts) { export function TokenSalt(json: TokenSaltOpts) {
return webapi.Post<String>(`/token/salt`, { json }) return webapi.Post<{ id: string, salt: string }>(`/token/salt`, { json })
} }
export interface PostOpts { export interface PostOpts {
user_id: String user_id: string
token?: String token?: string
salt?: String salt?: string
code?: String code?: string
app_id?: String app_id?: string
expired_at?: Date expired_at?: Date
over_perm?: String over_perm?: string
device?: String device?: string
} }
// keep
export function Post(json: PostOpts) { export function Post(json: PostOpts) {
return webapi.Post<models.Token>(`/token`, { json }) return webapi.Post<string>(`/token`, { json })
} }
export function Get(token_id: String) { export function Get(token_id: string) {
return webapi.Get<models.Token>(`/token/${token_id}`, {}) return webapi.Get<models.Token>(`/token/${token_id}`, {})
} }
export interface PatchOpts { export interface PatchOpts {
expired_at?: Date expired_at?: Date
over_perm?: String over_perm?: string
} }
export function Patch(token_id: String, json: PatchOpts) { export function Patch(token_id: string, json: PatchOpts) {
return webapi.Patch<models.Token>(`/token/${token_id}`, { json }) return webapi.Patch<models.Token>(`/token/${token_id}`, { json })
} }

@ -7,43 +7,43 @@
import webapi from "./webapi" import webapi from "./webapi"
import * as models from "./models" import * as models from "./models"
export interface PostOpts { export interface PostOpts {
username: String username: string
nickname?: String nickname?: string
icon?: String icon?: string
email?: String email?: string
phone?: String phone?: string
salt: String salt: string
code: String code: string
} }
export function Post(json: PostOpts) { export function Post(json: PostOpts) {
return webapi.Post<models.User>(`/user`, { json }) return webapi.Post<models.User>(`/user`, { json })
} }
export function UserRoleGet(user_role_id: String, user_id: String) { export function UserRoleGet(user_role_id: string, user_id: string) {
return webapi.Get<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, {}) return webapi.Get<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { })
} }
export interface UserRolePatchOpts { export interface UserRolePatchOpts {
status?: String status?: string
} }
export function UserRolePatch(user_role_id: String, user_id: String, json: UserRolePatchOpts) { export function UserRolePatch(user_role_id: string, user_id: string, json: UserRolePatchOpts) {
return webapi.Patch<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { json }) return webapi.Patch<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { json })
} }
export interface UserRoleDeleteOpts { export interface UserRoleDeleteOpts {
role_id: String role_id: string
app_id: String app_id: string
} }
export function UserRoleDelete(user_role_id: String, user_id: String, json: UserRoleDeleteOpts) { export function UserRoleDelete(user_role_id: string, user_id: string, json: UserRoleDeleteOpts) {
return webapi.Delete<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { json }) return webapi.Delete<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { json })
} }
export interface UserRolePostOpts { export interface UserRolePostOpts {
status: String status: string
role_id: String role_id: string
app_id: String app_id: string
} }
export function UserRolePost(user_id: String, json: UserRolePostOpts) { export function UserRolePost(user_id: string, json: UserRolePostOpts) {
return webapi.Post<models.UserRole>(`/user/${user_id}/user_role`, { json }) return webapi.Post<models.UserRole>(`/user/${user_id}/user_role`, { json })
} }
@ -52,39 +52,39 @@ export interface UserLoginOpts {
typ: String typ: String
} }
export function Get(user_id: String) { export function Get(user_id: string) {
return webapi.Get<models.User>(`/user/${user_id}`, {}) return webapi.Get<models.User>(`/user/${user_id}`, { })
} }
export function Delete(user_id: String) { export function Delete(user_id: string) {
return webapi.Delete<models.User>(`/user/${user_id}`, {}) return webapi.Delete<models.User>(`/user/${user_id}`, { })
} }
export interface UserRoleListOpts { export interface UserRoleListOpts {
status?: String status?: string
} }
export function UserRoleList(user_id: String, json: UserRoleListOpts) { export function UserRoleList(user_id: string, json: UserRoleListOpts) {
return webapi.Get<models.UserRole>(`/user/${user_id}/user_role`, { json }) return webapi.Get<models.UserRole>(`/user/${user_id}/user_role`, { json })
} }
export interface PatchOpts { export interface PatchOpts {
username?: String username?: string
nickname?: String nickname?: string
icon?: String icon?: string
email?: String email?: string
phone?: String phone?: string
status?: Number status?: number
} }
export function Patch(user_id: String, json: PatchOpts) { export function Patch(user_id: string, json: PatchOpts) {
return webapi.Patch<models.User>(`/user/${user_id}`, { json }) return webapi.Patch<models.User>(`/user/${user_id}`, { json })
} }
export interface ListOpts { export interface ListOpts {
username?: String username?: string
nickname?: String nickname?: string
email?: String email?: string
phone?: String phone?: string
status?: Number status?: number
} }
export function List(json: ListOpts) { export function List(json: ListOpts) {
return webapi.Get<models.User>(`/user`, { json }) return webapi.Get<models.User>(`/user`, { json })

@ -1,6 +1,6 @@
// //
// Copyright (C) 2024 veypi <i@veypi.com> // Copyright (C) 2024 veypi <i@veypi.com>
// 2024-10-11 00:21:45 // 2024-10-11 01:39:37
// Distributed under terms of the MIT license. // Distributed under terms of the MIT license.
// //
@ -41,34 +41,44 @@ const responseSuccess = (response: AxiosResponse) => {
// 这里没有必要进行判断axios 内部已经判断 // 这里没有必要进行判断axios 内部已经判断
// const isOk = 200 <= response.status && response.status < 300 // const isOk = 200 <= response.status && response.status < 300
let data = response.data let data = response.data
if (typeof data === 'object') {
if (data.code !== 0) {
return responseFailed({ response } as any)
}
data = data.data
}
return Promise.resolve(data) return Promise.resolve(data)
} }
const responseFailed = (error: AxiosError) => { const responseFailed = (error: AxiosError) => {
const { response, config } = error const { response } = error
const config = response?.config
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('请检查网络连接'))
} }
console.log(response) let needRetry = true
let needRetry = false if (response?.status == 404) {
needRetry = false
} else if (response?.status == 401) {
needRetry = false
if (data.code === 40103) {
}
}
if (!needRetry) { if (!needRetry) {
return Promise.reject(response?.data || response?.headers.error) return Promise.reject(data || response)
}; };
// @ts-ignore // @ts-ignore
const { __retryCount = 0, retryDelay = 1000, retryTimes } = config; const { __retryCount = 0, retryDelay = 1000, retryTimes } = config;
// 在请求对象上设置重试次数 // 在请求对象上设置重试次数
// @ts-ignore // @ts-ignore
config.__retryCount = __retryCount; config.__retryCount = __retryCount + 1;
// 判断是否超过了重试次数 // 判断是否超过了重试次数
if (__retryCount >= retryTimes) { if (__retryCount >= retryTimes) {
return Promise.reject(response?.data || response?.headers.error) return Promise.reject(response?.data || response?.headers.error)
} }
// 增加重试次数
// @ts-ignore
config.__retryCount++;
// 延时处理 // 延时处理
const delay = new Promise<void>((resolve) => { const delay = new Promise<void>((resolve) => {
setTimeout(() => { setTimeout(() => {

@ -0,0 +1,99 @@
/*
* auth.ts
* Copyright (C) 2024 veypi <i@veypi.com>
* 2024-10-11 12:01
* Distributed under terms of the MIT license.
*/
export interface modelsSimpleAuth {
level: number
name: string
tid: string
}
export const R = {
// 应用管理配置权限
App: 'app',
// 用户管理和绑定应用权限
User: 'user',
// 权限资源定义权限
Resource: 'resource',
// 角色管理和绑定用户权限
Role: 'role',
// 权限管理和绑定角色权限
Auth: 'auth',
}
export enum AccessLevel {
None = 0,
Do = 1,
Read = 1,
Create = 2,
Update = 3,
Delete = 4,
All = 5
}
export const LevelOptions = [
{ key: 0, name: '无权限' },
{ key: 1, name: '读取数据权限' },
{ key: 2, name: '创建数据权限' },
{ key: 3, name: '更新数据权限' },
{ key: 4, name: '删除数据权限' },
{ key: 5, name: '管理员权限' },
]
class authLevel {
level = AccessLevel.None
constructor(level: number) {
this.level = level
}
CanDo(): boolean {
return this.level >= AccessLevel.Do
}
CanRead(): boolean {
return this.level >= AccessLevel.Read
}
CanCreate(): boolean {
return this.level >= AccessLevel.Create
}
CanUpdate(): boolean {
return this.level >= AccessLevel.Update
}
CanDelete(): boolean {
return this.level >= AccessLevel.Delete
}
CanDoAny(): boolean {
return this.level >= AccessLevel.All
}
}
export class auths {
private readonly list: modelsSimpleAuth[]
constructor(auths: modelsSimpleAuth[]) {
this.list = auths
}
Get(name: string, rid: string): authLevel {
let l = AccessLevel.None
for (let i of this.list) {
if (i.name == name && (!i.tid || i.tid === rid) && i.level > l) {
l = i.level
}
}
return new authLevel(l)
}
}
export interface Auths {
Get(name: string, rid: string): authLevel
}
export function NewAuths(a: modelsSimpleAuth[]): Auths {
return new auths(a)
}

@ -6,6 +6,7 @@
*/ */
import api from './api' import api from './api'
export * from './models' import * as auth from './auth'
export { type Auths, type modelsSimpleAuth } from './models' // export * from './models'
export { api } import * as models from './models'
export { api, models, auth }

@ -0,0 +1,55 @@
/*
* models.ts
* Copyright (C) 2024 veypi <i@veypi.com>
* 2024-10-11 12:02
* Distributed under terms of the MIT license.
*/
export * from './api/models'
export type Dict = { [key: string]: any }
export enum ArgType {
Text = 'text',
Password = 'password',
Bool = 'bool',
Select = 'select',
Radio = 'radio',
Number = 'number',
Region = 'region',
NumList = 'numList',
StrList = 'strList',
Table = 'table',
Grid = 'grid',
File = 'file',
Img = 'img'
}
export const ArgTypesTrans = {
[ArgType.Text]: '文本',
[ArgType.Password]: '密码',
[ArgType.Select]: '选择器',
[ArgType.Radio]: '单选框',
[ArgType.Number]: '数字',
[ArgType.Region]: '区间',
[ArgType.NumList]: '数组',
[ArgType.StrList]: '文本集合',
[ArgType.Table]: '表格',
[ArgType.Grid]: '矩阵',
[ArgType.File]: '文件',
[ArgType.Img]: '图片',
[ArgType.Bool]: '开关',
}
export interface DocItem {
name: string
url: string
version?: string
}
export interface DocGroup {
name: string
icon: string
items?: DocItem[]
}

@ -10,7 +10,7 @@
export interface modelsSimpleAuth { export interface modelsSimpleAuth {
level: number level: number
name: string name: string
rid: string tid: string
} }
@ -82,7 +82,7 @@ export class auths {
Get(name: string, rid: string): authLevel { Get(name: string, rid: string): authLevel {
let l = AccessLevel.None let l = AccessLevel.None
for (let i of this.list) { for (let i of this.list) {
if (i.name == name && (!i.rid || i.rid === rid) && i.level > l) { if (i.name == name && (!i.tid || i.tid === rid) && i.level > l) {
l = i.level l = i.level
} }
} }

@ -5,139 +5,5 @@
* @descriptionindex * @descriptionindex
*/ */
import { AccessLevel } from './auth';
export { type Auths, type modelsSimpleAuth, NewAuths, R, AccessLevel, LevelOptions } from './auth' export { type Auths, type modelsSimpleAuth, NewAuths, R, AccessLevel, LevelOptions } from './auth'
export type Dict = { [key: string]: any }
export enum ArgType {
Text = 'text',
Password = 'password',
Bool = 'bool',
Select = 'select',
Radio = 'radio',
Number = 'number',
Region = 'region',
NumList = 'numList',
StrList = 'strList',
Table = 'table',
Grid = 'grid',
File = 'file',
Img = 'img'
}
export const ArgTypesTrans = {
[ArgType.Text]: '文本',
[ArgType.Password]: '密码',
[ArgType.Select]: '选择器',
[ArgType.Radio]: '单选框',
[ArgType.Number]: '数字',
[ArgType.Region]: '区间',
[ArgType.NumList]: '数组',
[ArgType.StrList]: '文本集合',
[ArgType.Table]: '表格',
[ArgType.Grid]: '矩阵',
[ArgType.File]: '文件',
[ArgType.Img]: '图片',
[ArgType.Bool]: '开关',
}
export interface DocItem {
name: string
url: string
version?: string
}
export interface DocGroup {
name: string
icon: string
items?: DocItem[]
}
export interface modelsBread {
Index: number
Name: string
Type?: string
RName: string
RParams?: any
RQuery?: any
}
export interface modelsApp {
created: string
updated: string
delete_flag: boolean
des: string
hide: boolean
icon: string
id: string
name: string
redirect: string
role_id: string
status: number
user_count: number
au: modelsAppUser
}
export enum AUStatus {
OK = 0,
Disabled = 1,
Applying = 2,
Deny = 3,
}
export interface modelsAppUser {
app: modelsApp,
user: modelsUser,
app_id: string
user_id: string
status: AUStatus
}
export interface modelsUser {
id: string
created: string
updated: string
username: string
nickname: string
email: string
phone: string
icon: string
status: number
used: number
space: number
au: AUStatus
}
export interface modelsAccess {
id: number
created: string
updated: string
name: string
app_id: string,
role_id?: string,
user_id?: string,
level: AccessLevel,
rid?: string
}
export interface modelsRole {
created: string
updated: string
app_id: string
id: string
name: string
des: string
user_count: number
}
export interface modelsResource {
created: string
updated: string
app_id: string
name: string
des: string
}

@ -65,18 +65,17 @@ const util = {
name + '=' + escape(value) + ';expires=' + exp.toLocaleString() name + '=' + escape(value) + ';expires=' + exp.toLocaleString()
}, },
getToken() { getToken() {
return localStorage.getItem('auth_token') || '' return localStorage.getItem('token') || ''
}, },
setToken(t: string) { setToken(t: string) {
localStorage.setItem('auth_token', t) localStorage.setItem('token', t)
bus.emit('token', t) bus.emit('token', t)
}, },
addTokenOf(url: string) { addTokenOf(url: string) {
return url + '?auth_token=' + encodeURIComponent(this.getToken()) return url + '?token=' + encodeURIComponent(this.getToken())
}, },
checkLogin() { checkLogin() {
// return parseInt(this.getCookie('stat')) === 1 return Boolean(localStorage.token)
return Boolean(localStorage.auth_token)
}, },
formatDate(date: Date, fmt: string) { formatDate(date: Date, fmt: string) {

@ -10,13 +10,13 @@
"postinstall": "nuxt prepare" "postinstall": "nuxt prepare"
}, },
"dependencies": { "dependencies": {
"@nuxt/ui": "^2.16.0",
"@pinia/nuxt": "^0.5.1", "@pinia/nuxt": "^0.5.1",
"@veypi/msg": "^0.2.0", "@veypi/msg": "^0.2.0",
"@veypi/oaer": "^0.2.4", "@veypi/oaer": "^0.2.4",
"@veypi/one-icon": "^3.0.0", "@veypi/one-icon": "^3.0.0",
"axios": "^1.7.2", "axios": "^1.7.2",
"cherry-markdown": "^0.8.42", "cherry-markdown": "^0.8.42",
"crypto-js": "^4.2.0",
"echarts": "^5.5.0", "echarts": "^5.5.0",
"js-base64": "^3.7.7", "js-base64": "^3.7.7",
"nuxt": "^3.11.2", "nuxt": "^3.11.2",
@ -25,6 +25,7 @@
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e", "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e",
"devDependencies": { "devDependencies": {
"@types/crypto-js": "^4.2.2",
"sass": "^1.77.4" "sass": "^1.77.4"
} }
} }

@ -88,7 +88,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import msg from '@veypi/msg'; import msg from '@veypi/msg';
import { Base64 } from 'js-base64'; import * as crypto from 'crypto-js'
definePageMeta({ definePageMeta({
@ -120,23 +120,70 @@ const check = () => {
checks.value.p = !Boolean(!data.value.password || !pReg.test(data.value.password)) checks.value.p = !Boolean(!data.value.password || !pReg.test(data.value.password))
checks.value.p2 = !Boolean(data.value.confirm !== data.value.password) checks.value.p2 = !Boolean(data.value.confirm !== data.value.password)
} }
function deriveKey(password: string, salt: any) {
return crypto.PBKDF2(password, salt, {
keySize: 256 / 32, iterations:
100, hasher: crypto.algo.SHA256
})
}
const login = () => { const login = () => {
enable_check.value = true enable_check.value = true
check() check()
if (!checks.value.u || !checks.value.p) { if (!checks.value.u || !checks.value.p) {
return return
} }
api.user.login(data.value.username,
{ client: 'vvv', typ: 'sss', pwd: Base64.encodeURL(data.value.password) }).then((data: any) => { api.token.TokenSalt({ username: data.value.username }).then(e => {
util.setToken(data.auth_token) let id = e.id
// msg.Info('') let key = deriveKey(data.value.password, e.salt)
// user.fetchUserData() let salt = crypto.lib.WordArray.random(128 / 8)
let url = route.query.redirect || data.redirect || '' let opts = {
console.log([url]) iv: salt,
redirect(url) mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
}
let p = crypto.AES.encrypt(e.id, key, opts)
api.token.Post({
user_id: id, code: p.toString(), salt:
salt.toString()
}).then(e => {
localStorage.setItem('refresh', e)
api.token.Post({ user_id: id, token: e }).then(e => {
localStorage.setItem('token', e)
console.log(e)
})
}).catch(e => { }).catch(e => {
msg.Warn(e) msg.Warn('登录失败:' + (e.err || e))
})
}) })
// api.user.salt(data.value.username).then((e: any) => {
// let id = e.data.id
// let key = deriveKey(data.value.password, e.data.salt)
// let salt = crypto.lib.WordArray.random(128 / 8)
// let opts = {
// iv: salt,
// mode: crypto.mode.CBC,
// padding: crypto.pad.Pkcs7
// }
// let p = crypto.AES.encrypt(id, key, opts)
// api.user.token(id, p.toString(), salt.toString()).then(e => {
// console.log(e)
// })
// })
// api.user.login(data.value.username,
// { client: 'vvv', typ: 'sss', pwd: Base64.encodeURL(data.value.password) }).then((data: any) => {
// util.setToken(data.auth_token)
// // msg.Info('')
// // user.fetchUserData()
// let url = route.query.redirect || data.redirect || ''
// console.log([url])
// redirect(url)
// }).catch(e => {
// msg.Warn(e)
// })
} }
const register = () => { const register = () => {
enable_check.value = true enable_check.value = true
@ -144,16 +191,18 @@ const register = () => {
if (!checks.value.u || !checks.value.p || !checks.value.p2) { if (!checks.value.u || !checks.value.p || !checks.value.p2) {
return return
} }
let salt = crypto.lib.WordArray.random(128 / 8).toString()
let key = deriveKey(data.value.password, salt)
api.user.reg({ api.user.reg({
username: data.value.username, pwd: username: data.value.username,
Base64.encodeURL(data.value.password) salt: salt,
}).then(u => { code: key.toString(crypto.enc.Hex)
console.log(u) }).then(() => {
msg.Info('注册成功') msg.Info('注册成功')
aOpt.value = '' aOpt.value = ''
}).catch(e => { }).catch(e => {
console.log(e) console.log(e)
msg.Warn('注册失败:' + e) msg.Warn('注册失败:' + (e.err || e))
}) })
} }
const reset = () => { const reset = () => {
@ -243,6 +292,7 @@ onMounted(() => {
position: sticky; position: sticky;
padding: 2rem; padding: 2rem;
width: 50%; width: 50%;
max-width: 50rem;
min-width: 20rem; min-width: 20rem;
height: 50%; height: 50%;

@ -5,14 +5,14 @@
* Distributed under terms of the MIT license. * Distributed under terms of the MIT license.
*/ */
import { type Auths } from '@/composables/models'
import { Base64 } from 'js-base64' import { Base64 } from 'js-base64'
import type { auth, models } from '~/composables';
export const useUserStore = defineStore('user', { export const useUserStore = defineStore('user', {
state: () => ({ state: () => ({
id: '', id: '',
local: {} as modelsUser, local: {} as models.User,
auth: {} as Auths, auth: {} as auth.Auths,
ready: false ready: false
}), }),
getters: { getters: {
@ -30,12 +30,12 @@ export const useUserStore = defineStore('user', {
return false return false
} }
let data = JSON.parse(Base64.decode(token[1])) let data = JSON.parse(Base64.decode(token[1]))
if (data.id) { if (data.uid) {
let l = 'access to' let l = 'access to'
data.access.map((e: any) => l = l + `\n${e.name}.${e.level}`) data.access.map((e: any) => l = l + `\n${e.name}.${e.level}`)
console.log(l) console.log(l)
this.auth = NewAuths(data.access) this.auth = NewAuths(data.access)
api.user.get(data.id).then((e: modelsUser) => { api.user.Get(data.id).then((e) => {
this.id = e.id this.id = e.id
this.local = e this.local = e
this.ready = true this.ready = true

@ -1513,6 +1513,11 @@
dependencies: dependencies:
"@types/tern" "*" "@types/tern" "*"
"@types/crypto-js@^4.2.2":
version "4.2.2"
resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.2.2.tgz#771c4a768d94eb5922cc202a3009558204df0cea"
integrity sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==
"@types/dompurify@^2.2.3": "@types/dompurify@^2.2.3":
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.4.0.tgz#fd9706392a88e0e0e6d367f3588482d817df0ab9" resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.4.0.tgz#fd9706392a88e0e0e6d367f3588482d817df0ab9"
@ -2691,6 +2696,11 @@ crypt@0.0.2:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
crypto-js@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
css-declaration-sorter@^7.2.0: css-declaration-sorter@^7.2.0:
version "7.2.0" version "7.2.0"
resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024" resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024"

Loading…
Cancel
Save