SAML; Dashboard
This commit is contained in:
@@ -4,7 +4,7 @@ class ActionService {
|
||||
async perform({ text, action, ...args }) {
|
||||
if ( action === 'redirect' ) {
|
||||
if ( args.next ) {
|
||||
return location_service.redirect(args.next, 1500)
|
||||
return location_service.redirect(args.next, args.delay || 1500)
|
||||
}
|
||||
} else {
|
||||
throw new TypeError(`Unknown action type: ${action}`)
|
||||
|
||||
@@ -4,10 +4,10 @@ class AuthAPI {
|
||||
return result && result.data && result.data.data && result.data.data.is_valid
|
||||
}
|
||||
|
||||
async attempt({ username, password, create_session }) {
|
||||
async attempt({ username, password, create_session, ...others }) {
|
||||
try {
|
||||
const result = await axios.post('/api/v1/auth/attempt', {
|
||||
username, password, create_session
|
||||
username, password, create_session, ...others
|
||||
})
|
||||
|
||||
if ( result && result.data && result.data.data && result.data.data ) {
|
||||
@@ -32,6 +32,30 @@ class AuthAPI {
|
||||
const result = await axios.post('/api/v1/auth/mfa/enable')
|
||||
return result && result.data && result.data.data && result.data.data.success && result.data.data.mfa_enabled
|
||||
}
|
||||
|
||||
async mfa_disable() {
|
||||
const result = await axios.post('/api/v1/auth/mfa/disable')
|
||||
return result && result.data && result.data.data && result.data.data.success && !result.data.data.mfa_enabled
|
||||
}
|
||||
|
||||
async has_mfa() {
|
||||
const result = await axios.get('/api/v1/auth/mfa/enable/date')
|
||||
if ( result && result.data && result.data.data ) return result.data.data
|
||||
}
|
||||
|
||||
async app_passwords() {
|
||||
const result = await axios.get('/api/v1/password/app_passwords')
|
||||
if ( result && result.data && Array.isArray(result.data.data) ) return result.data.data
|
||||
}
|
||||
|
||||
async create_app_password(name) {
|
||||
const result = await axios.post('/api/v1/password/app_passwords', { name })
|
||||
if ( result && result.data && result.data.data ) return result.data.data
|
||||
}
|
||||
|
||||
async delete_app_password(uuid) {
|
||||
await axios.delete(`/api/v1/password/app_passwords/${uuid}`)
|
||||
}
|
||||
}
|
||||
|
||||
const auth_api = new AuthAPI()
|
||||
|
||||
37
app/assets/app/service/EventBus.service.js
Normal file
37
app/assets/app/service/EventBus.service.js
Normal file
@@ -0,0 +1,37 @@
|
||||
class Event {
|
||||
firings = []
|
||||
subscriptions = []
|
||||
|
||||
constructor(name) {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
subscribe(handler) {
|
||||
if ( typeof handler !== 'function' ) {
|
||||
throw new TypeError('Event subscription handlers must be functions.')
|
||||
}
|
||||
|
||||
this.subscriptions.push(handler)
|
||||
}
|
||||
|
||||
async fire(...args) {
|
||||
this.firings.push({ args })
|
||||
|
||||
return Promise.all(this.subscriptions.map(x => x(...args)))
|
||||
}
|
||||
}
|
||||
|
||||
class EventBusService {
|
||||
_events = {}
|
||||
|
||||
event(name) {
|
||||
if ( !this._events[name] ) {
|
||||
this._events[name] = new Event(name)
|
||||
}
|
||||
|
||||
return this._events[name]
|
||||
}
|
||||
}
|
||||
|
||||
const event_bus = new EventBusService()
|
||||
export { event_bus, Event }
|
||||
@@ -11,6 +11,15 @@ class LocationService {
|
||||
async back() {
|
||||
return window.history.back()
|
||||
}
|
||||
|
||||
async reload(delay = 0) {
|
||||
return new Promise(res => {
|
||||
setTimeout(() => {
|
||||
window.location.reload()
|
||||
res()
|
||||
}, delay)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const location_service = new LocationService()
|
||||
|
||||
56
app/assets/app/service/Message.service.js
Normal file
56
app/assets/app/service/Message.service.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { event_bus } from './EventBus.service.js'
|
||||
|
||||
class MessageService {
|
||||
listener_interval = 25000
|
||||
|
||||
alert({type, message, timeout = 0, on_dismiss = () => {} }) {
|
||||
event_bus.event('message.alert').fire({ type, message, timeout, on_dismiss })
|
||||
}
|
||||
|
||||
modal({title, message, buttons = [] }) {
|
||||
event_bus.event('message.modal').fire({ title, message, buttons })
|
||||
}
|
||||
|
||||
async fetch() {
|
||||
const result = await axios.get('/api/v1/message/banners')
|
||||
if ( result && result.data && result.data.data ) return result.data.data
|
||||
}
|
||||
|
||||
async dismiss(banner_id) {
|
||||
return axios.post(`/api/v1/message/banners/read/${banner_id}`)
|
||||
}
|
||||
|
||||
init_listener() {
|
||||
this.message_ids = []
|
||||
this.listener = setInterval(() => this._listener_tick(), this.listener_interval)
|
||||
window.addEventListener('beforeunload', () => this.stop_listener())
|
||||
this._listener_tick()
|
||||
}
|
||||
|
||||
async _listener_tick() {
|
||||
const result = await this.fetch()
|
||||
if ( result ) {
|
||||
for ( const banner of result ) {
|
||||
if ( this.message_ids.includes(banner.id) ) continue
|
||||
|
||||
this.message_ids.push(banner.id)
|
||||
await this.alert({
|
||||
type: banner.type,
|
||||
message: banner.message,
|
||||
on_dismiss: (e) => {
|
||||
this.dismiss(banner.id).then(() => {
|
||||
this.message_ids = this.message_ids.filter(x => x !== banner.id)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stop_listener() {
|
||||
clearInterval(this.listener)
|
||||
}
|
||||
}
|
||||
|
||||
const message_service = new MessageService()
|
||||
export { message_service }
|
||||
13
app/assets/app/service/Password.service.js
Normal file
13
app/assets/app/service/Password.service.js
Normal file
@@ -0,0 +1,13 @@
|
||||
class PasswordService {
|
||||
async get_resets() {
|
||||
const result = await axios.get('/api/v1/password/resets')
|
||||
if ( result && result.data && result.data.data ) return result.data.data
|
||||
}
|
||||
|
||||
async reset(password) {
|
||||
await axios.post('/api/v1/password/resets', { password })
|
||||
}
|
||||
}
|
||||
|
||||
const password_service = new PasswordService()
|
||||
export { password_service }
|
||||
15
app/assets/app/service/Profile.service.js
Normal file
15
app/assets/app/service/Profile.service.js
Normal file
@@ -0,0 +1,15 @@
|
||||
class ProfileService {
|
||||
|
||||
async get_profile(user_id = 'me') {
|
||||
const results = await axios.get(`/api/v1/profile/${user_id}`)
|
||||
if ( results && results.data && results.data.data ) return results.data.data
|
||||
}
|
||||
|
||||
async update_profile({ user_id, first_name, last_name, email, tagline = undefined }) {
|
||||
await axios.patch(`/api/v1/profile/${user_id}`, { first_name, last_name, email, tagline })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const profile_service = new ProfileService()
|
||||
export { profile_service }
|
||||
32
app/assets/app/service/Session.service.js
Normal file
32
app/assets/app/service/Session.service.js
Normal file
@@ -0,0 +1,32 @@
|
||||
class Session {
|
||||
data = {}
|
||||
|
||||
init(data) {
|
||||
this.data = data
|
||||
}
|
||||
|
||||
get(key) {
|
||||
const parts = key.split('.')
|
||||
let value = this.data
|
||||
for ( const part of parts ) {
|
||||
value = value[part]
|
||||
if ( typeof value === 'undefined' ) return value
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
const parts = key.split('.')
|
||||
let parent = this.data
|
||||
|
||||
for ( const part of parts.slice(0, -1) ) {
|
||||
if ( !parent[part] ) parent[part] = {}
|
||||
parent = parent[part]
|
||||
}
|
||||
|
||||
parent[parts.reverse()[0]] = value
|
||||
}
|
||||
}
|
||||
|
||||
const session = new Session()
|
||||
export { session }
|
||||
24
app/assets/app/service/Utility.service.js
Normal file
24
app/assets/app/service/Utility.service.js
Normal file
@@ -0,0 +1,24 @@
|
||||
class UtilityService {
|
||||
_debounce_timeouts = {}
|
||||
|
||||
uuid() {
|
||||
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
|
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||
)
|
||||
}
|
||||
|
||||
debounce(handler = () => {}, delay = 500) {
|
||||
let timeout = null
|
||||
|
||||
return (...args) => {
|
||||
clearTimeout(timeout)
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
handler(...args)
|
||||
}, delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const utility = new UtilityService()
|
||||
export { utility }
|
||||
Reference in New Issue
Block a user