mirror of https://github.com/veypi/OneAuth.git
feat: update token api
parent
40d27cb9e4
commit
3b65aea4ad
@ -1 +1,3 @@
|
||||
export function setupCounter(element: HTMLButtonElement): void
|
||||
export default interface OAER {
|
||||
logout()
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (C) 2024 veypi <i@veypi.com>
|
||||
// 2024-10-11 14:36:07
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
import webapi from "./webapi"
|
||||
import * as models from "./models"
|
||||
export interface ListOpts {
|
||||
app_id: string
|
||||
user_id?: string
|
||||
role_id?: string
|
||||
name?: string
|
||||
}
|
||||
export interface ListQuery {
|
||||
created_at?: Date
|
||||
updated_at?: Date
|
||||
}
|
||||
export function List(json: ListOpts, query: ListQuery) {
|
||||
return webapi.Get<[models.Access]>(`/access`, { json, query })
|
||||
}
|
||||
|
||||
export interface PostOpts {
|
||||
app_id: string
|
||||
user_id?: string
|
||||
role_id?: string
|
||||
name: string
|
||||
t_id: string
|
||||
level: number
|
||||
}
|
||||
export function Post(json: PostOpts) {
|
||||
return webapi.Post<models.Access>(`/access`, { json })
|
||||
}
|
||||
|
@ -1,35 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2019 light <veypi@light-laptop>
|
||||
*
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
import user from './user'
|
||||
import app from './app'
|
||||
import cfg from '../cfg'
|
||||
import ajax from './axios'
|
||||
import nats from './nats'
|
||||
import tsdb from './tsdb'
|
||||
import * as user from "./user"
|
||||
import * as token from "./token"
|
||||
import * as role from "./role"
|
||||
import * as app from "./app"
|
||||
import * as access from "./access"
|
||||
import webapi, { token as apitoken } from "./webapi"
|
||||
|
||||
|
||||
const api = {
|
||||
nats: nats,
|
||||
tsdb: tsdb,
|
||||
user: user,
|
||||
app: app,
|
||||
info: () => {
|
||||
return ajax.get(cfg.BaseUrl() + '/info')
|
||||
},
|
||||
refresh_token: () => {
|
||||
ajax.post(cfg.BaseUrl() + '/app/' + cfg.uuid + '/token/', { app_id: cfg.uuid, token: cfg.refresh }).then(e => {
|
||||
cfg.token = e
|
||||
// bus.emit('sync', e)
|
||||
}).catch(e => {
|
||||
console.warn(e)
|
||||
// bus.emit('logout', 'get token failed ' + e)
|
||||
})
|
||||
const info = () => {
|
||||
return webapi.Get<{
|
||||
id: string
|
||||
}>('/', {})
|
||||
}
|
||||
|
||||
export {
|
||||
apitoken
|
||||
}
|
||||
|
||||
export { api }
|
||||
export default api
|
||||
export default {
|
||||
info,
|
||||
user,
|
||||
token,
|
||||
role,
|
||||
app,
|
||||
access
|
||||
}
|
||||
|
@ -0,0 +1,81 @@
|
||||
export interface Access {
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
app_id: string
|
||||
user_id?: string
|
||||
role_id?: string
|
||||
name: string
|
||||
tid: string
|
||||
level: number
|
||||
}
|
||||
export interface App {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
name: string
|
||||
icon: string
|
||||
des: string
|
||||
participate: string
|
||||
init_role_id?: string
|
||||
init_role?: Role
|
||||
init_url: string
|
||||
user_count: number
|
||||
}
|
||||
export interface AppUser {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
app_id: string
|
||||
user_id: string
|
||||
status: string
|
||||
app?: App
|
||||
user?: User
|
||||
}
|
||||
export interface Resource {
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
app_id: string
|
||||
name: string
|
||||
des: string
|
||||
}
|
||||
export interface Role {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
name: string
|
||||
des: string
|
||||
app_id: string
|
||||
user_count: number
|
||||
}
|
||||
export interface Token {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
user_id: string
|
||||
app_id: string
|
||||
expired_at: Date
|
||||
over_perm: string
|
||||
device: string
|
||||
ip: string
|
||||
}
|
||||
export interface User {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
username: string
|
||||
nickname: string
|
||||
icon: string
|
||||
email: string
|
||||
phone: string
|
||||
status: number
|
||||
}
|
||||
export interface UserRole {
|
||||
id: string
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
user_id: string
|
||||
role_id: string
|
||||
app_id: string
|
||||
status: string
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* nats.ts
|
||||
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||
* 2023-10-19 21:36
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
|
||||
import cfg from '../cfg'
|
||||
import ajax from './axios'
|
||||
|
||||
export default {
|
||||
local: () => cfg.BaseUrl() + '/nats/',
|
||||
general() {
|
||||
return ajax.get(this.local() + 'varz')
|
||||
},
|
||||
conns() {
|
||||
return ajax.get(this.local() + 'connz', { subs: true })
|
||||
},
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright (C) 2024 veypi <i@veypi.com>
|
||||
// 2024-10-11 14:36:07
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
import webapi from "./webapi"
|
||||
import * as models from "./models"
|
||||
export function Get(role_id: string) {
|
||||
return webapi.Get<models.Role>(`/role/${role_id}`, { })
|
||||
}
|
||||
|
||||
export interface PatchOpts {
|
||||
name?: string
|
||||
des?: string
|
||||
app_id?: string
|
||||
}
|
||||
export function Patch(role_id: string, json: PatchOpts) {
|
||||
return webapi.Patch<models.Role>(`/role/${role_id}`, { json })
|
||||
}
|
||||
|
||||
export function Delete(role_id: string) {
|
||||
return webapi.Delete<models.Role>(`/role/${role_id}`, { })
|
||||
}
|
||||
|
||||
export interface PostOpts {
|
||||
name: string
|
||||
des: string
|
||||
app_id: string
|
||||
}
|
||||
export function Post(json: PostOpts) {
|
||||
return webapi.Post<models.Role>(`/role`, { json })
|
||||
}
|
||||
|
||||
export interface ListOpts {
|
||||
name?: string
|
||||
}
|
||||
export function List(json: ListOpts) {
|
||||
return webapi.Get<[models.Role]>(`/role`, { json })
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright (C) 2024 veypi <i@veypi.com>
|
||||
// 2024-10-11 14:36:07
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
import webapi from "./webapi"
|
||||
import * as models from "./models"
|
||||
export interface TokenSaltOpts {
|
||||
username: string
|
||||
typ?: string
|
||||
}
|
||||
// keep
|
||||
export function TokenSalt(json: TokenSaltOpts) {
|
||||
return webapi.Post<{ id: string, salt: string }>(`/token/salt`, { json })
|
||||
}
|
||||
export interface PostOpts {
|
||||
user_id: string
|
||||
refresh?: string
|
||||
salt?: string
|
||||
code?: string
|
||||
app_id?: string
|
||||
expired_at?: Date
|
||||
over_perm?: string
|
||||
device?: string
|
||||
}
|
||||
|
||||
// keep
|
||||
export function Post(json: PostOpts) {
|
||||
return webapi.Post<string>(`/token`, { json })
|
||||
}
|
||||
export function Get(token_id: string) {
|
||||
return webapi.Get<models.Token>(`/token/${token_id}`, {})
|
||||
}
|
||||
|
||||
export interface PatchOpts {
|
||||
expired_at?: Date
|
||||
over_perm?: string
|
||||
}
|
||||
export function Patch(token_id: string, json: PatchOpts) {
|
||||
return webapi.Patch<models.Token>(`/token/${token_id}`, { json })
|
||||
}
|
||||
|
||||
export function Delete(token_id: string) {
|
||||
return webapi.Delete<models.Token>(`/token/${token_id}`, {})
|
||||
}
|
||||
|
||||
export interface ListOpts {
|
||||
user_id: string
|
||||
app_id: string
|
||||
}
|
||||
export function List(json: ListOpts) {
|
||||
return webapi.Get<[models.Token]>(`/token`, { json })
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* tsdb.ts
|
||||
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||
* 2023-10-20 23:21
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
|
||||
import cfg from '../cfg'
|
||||
import ajax from './axios'
|
||||
|
||||
export default {
|
||||
local: () => cfg.BaseUrl() + '/ts/',
|
||||
range(query: string, props?: { start?: string, end?: string, step?: string, query?: string }) {
|
||||
if (query !== undefined) {
|
||||
// @ts-ignore
|
||||
props.query = query
|
||||
} else {
|
||||
props = { query: query }
|
||||
}
|
||||
return ajax.get(this.local() + 'query_range', props)
|
||||
},
|
||||
query(query: string) {
|
||||
return ajax.get(this.local() + 'query', { query: query })
|
||||
}
|
||||
}
|
@ -1,24 +1,87 @@
|
||||
/*
|
||||
* user.ts
|
||||
* Copyright (C) 2023 veypi <i@veypi.com>
|
||||
* 2023-10-05 15:37
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
//
|
||||
// Copyright (C) 2024 veypi <i@veypi.com>
|
||||
// 2024-10-11 14:35:47
|
||||
// Distributed under terms of the MIT license.
|
||||
//
|
||||
|
||||
import webapi from "./webapi"
|
||||
import * as models from "./models"
|
||||
export function Get(user_id: string) {
|
||||
return webapi.Get<models.User>(`/user/${user_id}`, { })
|
||||
}
|
||||
|
||||
export interface PatchOpts {
|
||||
username?: string
|
||||
nickname?: string
|
||||
icon?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
status?: number
|
||||
}
|
||||
export function Patch(user_id: string, json: PatchOpts) {
|
||||
return webapi.Patch<models.User>(`/user/${user_id}`, { json })
|
||||
}
|
||||
|
||||
export function Delete(user_id: string) {
|
||||
return webapi.Delete<models.User>(`/user/${user_id}`, { })
|
||||
}
|
||||
|
||||
export interface PostOpts {
|
||||
username: string
|
||||
nickname?: string
|
||||
icon?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
salt: string
|
||||
code: string
|
||||
}
|
||||
export function Post(json: PostOpts) {
|
||||
return webapi.Post<models.User>(`/user`, { json })
|
||||
}
|
||||
|
||||
export interface ListOpts {
|
||||
username?: string
|
||||
nickname?: string
|
||||
email?: string
|
||||
phone?: string
|
||||
status?: number
|
||||
}
|
||||
export function List(json: ListOpts) {
|
||||
return webapi.Get<[models.User]>(`/user`, { json })
|
||||
}
|
||||
|
||||
export function UserRoleGet(user_role_id: string, user_id: string) {
|
||||
return webapi.Get<models.UserRole>(`/user/${user_id}/user_role/${user_role_id}`, { })
|
||||
}
|
||||
|
||||
import ajax from './axios'
|
||||
import cfg from '../cfg'
|
||||
export interface UserRolePatchOpts {
|
||||
status?: string
|
||||
}
|
||||
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 })
|
||||
}
|
||||
|
||||
export interface UserRoleDeleteOpts {
|
||||
role_id: string
|
||||
app_id: string
|
||||
}
|
||||
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 })
|
||||
}
|
||||
|
||||
export interface UserRolePostOpts {
|
||||
status: string
|
||||
role_id: string
|
||||
app_id: string
|
||||
}
|
||||
export function UserRolePost(user_id: string, json: UserRolePostOpts) {
|
||||
return webapi.Post<models.UserRole>(`/user/${user_id}/user_role`, { json })
|
||||
}
|
||||
|
||||
export default {
|
||||
local: () => cfg.BaseUrl() + '/user/',
|
||||
search(q: string) {
|
||||
return ajax.get(this.local(), { username: q })
|
||||
},
|
||||
get(id: number) {
|
||||
return ajax.get(this.local() + id)
|
||||
},
|
||||
export interface UserRoleListOpts {
|
||||
status?: string
|
||||
}
|
||||
export function UserRoleList(user_id: string, json: UserRoleListOpts) {
|
||||
return webapi.Get<[models.UserRole]>(`/user/${user_id}/user_role`, { json })
|
||||
}
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* cfg.ts
|
||||
* Copyright (C) 2024 veypi <i@veypi.com>
|
||||
* 2024-07-03 18:22
|
||||
* Distributed under terms of the MIT license.
|
||||
*/
|
||||
|
||||
import proxy from './components/proxy'
|
||||
let cfg = proxy.Watch({
|
||||
uuid: '',
|
||||
refresh: '',
|
||||
token: '',
|
||||
|
||||
|
||||
app_data: {},
|
||||
user: {
|
||||
username: 'asd',
|
||||
nickname: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
id: 1,
|
||||
icon: 'https://public.veypi.com/img/avatar/0001.jpg'
|
||||
},
|
||||
myapps: [
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
],
|
||||
ready: false,
|
||||
local_user: {},
|
||||
|
||||
host: '',
|
||||
_host_nats: '',
|
||||
nats_pub_key: '',
|
||||
prefix: '/api',
|
||||
BaseUrl() {
|
||||
return this.host + this.prefix
|
||||
},
|
||||
NatsHost() {
|
||||
if (this._host_nats.startsWith('ws')) {
|
||||
return this._host_nats
|
||||
}
|
||||
return 'ws://' + this._host_nats
|
||||
},
|
||||
media(u: string) {
|
||||
return this.host + u
|
||||
},
|
||||
goto(url: string) {
|
||||
if (url.startsWith('http')) {
|
||||
window.location.href = url
|
||||
return
|
||||
}
|
||||
if (!url.startsWith('/')) {
|
||||
url = '/' + url
|
||||
}
|
||||
window.location.href = this.host + url
|
||||
},
|
||||
Host() {
|
||||
return this.host || window.location.host
|
||||
},
|
||||
userFileUrl() {
|
||||
return '/fs/u/'
|
||||
},
|
||||
appFileUrl() {
|
||||
return `/fs/a/${this.uuid}/`
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
export default cfg
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* logic.ts
|
||||
* Copyright (C) 2024 veypi <i@veypi.com>
|
||||
* 2024-10-24 16:36
|
||||
* Distributed under terms of the GPL license.
|
||||
*/
|
||||
import bus from './bus'
|
||||
import proxy from './components/proxy'
|
||||
import api, { apitoken } from './api'
|
||||
|
||||
class Token {
|
||||
iat?: string
|
||||
iss?: string
|
||||
jti?: string
|
||||
exp?: number
|
||||
aid?: string
|
||||
icon?: string
|
||||
name?: string
|
||||
uid?: string
|
||||
access?: any
|
||||
private _raw: string
|
||||
private _typ: 'refresh' | 'oa' | 'app'
|
||||
constructor(typ: 'refresh' | 'oa' | 'app') {
|
||||
this._typ = typ
|
||||
this._raw = localStorage.getItem(typ) || ''
|
||||
if (this._raw) {
|
||||
this.set(this._raw)
|
||||
}
|
||||
}
|
||||
isVaild() {
|
||||
if (this.exp) {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
return now < this.exp
|
||||
}
|
||||
return false
|
||||
}
|
||||
set(t: string) {
|
||||
try {
|
||||
const parts = t.split('.');
|
||||
// header = JSON.parse(atob(parts[0]));
|
||||
let body = JSON.parse(atob(parts[1]));
|
||||
// sign = parts[2]
|
||||
this._raw = t
|
||||
Object.assign(this, body)
|
||||
localStorage.setItem(this._typ, t)
|
||||
} catch (error) {
|
||||
console.warn('Error parsing JWT:', error);
|
||||
}
|
||||
}
|
||||
clear() {
|
||||
localStorage.removeItem(this._typ)
|
||||
this.exp = undefined
|
||||
}
|
||||
raw() {
|
||||
return this._raw
|
||||
}
|
||||
update() {
|
||||
return new Promise<Token>((resolve, reject) => {
|
||||
if (!logic.token.refresh.isVaild() || this._typ === 'refresh') {
|
||||
reject()
|
||||
}
|
||||
let aid = logic.oa_id
|
||||
if (this._typ === 'app') {
|
||||
aid = logic.app_id
|
||||
}
|
||||
api.token.Post({ refresh: logic.token.refresh.raw(), user_id: logic.token.refresh.uid!, app_id: aid }).then(e => {
|
||||
if (this._typ === 'oa' && logic.app_id == logic.oa_id) {
|
||||
logic.token.app.set(e)
|
||||
}
|
||||
this.set(e)
|
||||
resolve(this)
|
||||
}).catch(e => {
|
||||
console.warn(`get oa token failed: ${e} `)
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// interface Token {
|
||||
// aid: string
|
||||
// exp: number
|
||||
// iat: string
|
||||
// icon: string
|
||||
// iss: string
|
||||
// jti: string
|
||||
// name: string
|
||||
// uid: string
|
||||
// isVaild: () => boolean
|
||||
// row: () => string
|
||||
// }
|
||||
|
||||
const logic = proxy.Watch({
|
||||
oa_id: '',
|
||||
app_id: '',
|
||||
token: {
|
||||
refresh: new Token('refresh'),
|
||||
oa: new Token('oa'),
|
||||
app: new Token('app'),
|
||||
},
|
||||
|
||||
user: {
|
||||
username: 'asd',
|
||||
nickname: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
id: 1,
|
||||
icon: 'https://public.veypi.com/img/avatar/0001.jpg'
|
||||
},
|
||||
myapps: [
|
||||
{ name: 'a' },
|
||||
{ name: 'b' },
|
||||
],
|
||||
ready: false,
|
||||
init: () => {
|
||||
return new Promise<Token>((resolve, reject) => {
|
||||
api.info().then(e => {
|
||||
logic.oa_id = e.id
|
||||
if (logic.token.refresh.isVaild()) {
|
||||
logic.app_id = logic.token.refresh.aid!
|
||||
logic.token.oa.update().then((e) => {
|
||||
apitoken.set_updator(logic.token.oa.update)
|
||||
if (logic.app_id !== logic.oa_id) {
|
||||
logic.token.app.update().then((e) => {
|
||||
logic.ready = true
|
||||
resolve(e);
|
||||
}).catch(() => reject())
|
||||
} else {
|
||||
logic.ready = true
|
||||
resolve(e);
|
||||
}
|
||||
}).catch(() => {
|
||||
reject()
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
}).catch(e => {
|
||||
console.warn(`can not get info from ${logic.host}: ${e} `)
|
||||
reject();
|
||||
})
|
||||
})
|
||||
},
|
||||
host: '',
|
||||
Host() {
|
||||
return this.host || (window.location.protocol + window.location.host)
|
||||
},
|
||||
goto(url: string) {
|
||||
if (url.startsWith('http')) {
|
||||
window.location.href = url
|
||||
return
|
||||
}
|
||||
if (!url.startsWith('/')) {
|
||||
url = '/' + url
|
||||
}
|
||||
window.location.href = this.host + url
|
||||
},
|
||||
})
|
||||
|
||||
bus.on('login', () => {
|
||||
logic.goto('/login')
|
||||
})
|
||||
bus.on('logout', () => {
|
||||
logic.ready = false
|
||||
logic.token.refresh.clear()
|
||||
logic.token.oa.clear()
|
||||
logic.token.app.clear()
|
||||
})
|
||||
|
||||
export default logic
|
@ -1,6 +1,7 @@
|
||||
import './style.css'
|
||||
import { OAer } from '../lib/main'
|
||||
import oaer from '../lib/main'
|
||||
|
||||
let t = new OAer('http://localhost:3000', 'voa')
|
||||
console.log(t.domid)
|
||||
oaer.init('http://localhost:3000', '')
|
||||
oaer.render_ui('voa')
|
||||
console.log(oaer)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue