updating web app output path

This commit is contained in:
Roland Osborne 2022-06-08 12:52:06 -07:00
parent 74244b920d
commit f93b51c862
15 changed files with 134 additions and 50 deletions

View File

@ -12,8 +12,15 @@ import (
func AddAccount(w http.ResponseWriter, r *http.Request) {
var token *store.AccountToken
var res error
if r.Header.Get("Authorization") == "" {
if r.FormValue("token") != "" {
token, _, res = AccessToken(r)
if res != nil || token.TokenType != APP_TOKENCREATE {
ErrResponse(w, http.StatusUnauthorized, res)
return
}
} else {
if available, err := getAvailableAccounts(); err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
@ -21,13 +28,6 @@ func AddAccount(w http.ResponseWriter, r *http.Request) {
ErrResponse(w, http.StatusForbidden, errors.New("no open accounts available"))
return
}
} else {
var err error
token, err = BearerAccountToken(r);
if err != nil || token.TokenType != APP_TOKENCREATE {
ErrResponse(w, http.StatusUnauthorized, err)
return
}
}
username, password, ret := BasicCredentials(r);

View File

@ -11,21 +11,19 @@ type accountUsername struct {
}
func GetAccountUsername(w http.ResponseWriter, r *http.Request) {
var token *store.AccountToken
if r.Header.Get("Authorization") == "" {
if r.FormValue("token") != "" {
token, _, res := AccessToken(r)
if res != nil || token.TokenType != APP_TOKENCREATE {
ErrResponse(w, http.StatusUnauthorized, res)
return
}
} else {
if available, err := getAvailableAccounts(); err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
} else if available == 0 {
ErrResponse(w, http.StatusUnauthorized, errors.New("no open accounts available"))
return
}
} else {
var err error
token, err = BearerAccountToken(r);
if err != nil || token.TokenType != APP_TOKENCREATE {
ErrResponse(w, http.StatusUnauthorized, err)
ErrResponse(w, http.StatusForbidden, errors.New("no open accounts available"))
return
}
}

View File

@ -34,7 +34,7 @@ func NewRouter() *mux.Router {
Handler(handler)
}
fs := http.FileServer(http.Dir("/data/databag/net/web/build/"))
fs := http.FileServer(http.Dir("/app/databag/net/web/build/"))
router.PathPrefix("/").Handler(http.StripPrefix("/", fs))
return router

View File

@ -45,7 +45,7 @@ export function AccountItem({ token, item, remove }) {
<div class="control">
<Tooltip placement="topLeft" title="Account Login Link">
<ResetButton type="text" size="large" icon={<UnlockOutlined />}
onClick={() => actions.setAccessLink()}></ResetButton>
loading={state.accessBusy} onClick={() => actions.setAccessLink()}></ResetButton>
</Tooltip>
<Enable />
<Tooltip placement="topLeft" title="Delete Account">
@ -53,7 +53,7 @@ export function AccountItem({ token, item, remove }) {
loading={state.removeBusy} onClick={() => actions.remove()}></DeleteButton>
</Tooltip>
</div>
<Modal title="Access Link" visible={state.showAccess} centered width="fitContent"
<Modal title="Access Account Link" visible={state.showAccess} centered width="fitContent"
footer={[ <Button type="primary" onClick={() => actions.setShowAccess(false)}>OK</Button> ]}
onCancel={() => actions.setShowAccess(false)}>
<AccessLayout>

View File

@ -8,6 +8,7 @@ export function useAccountItem(token, item, remove) {
const [state, setState] = useState({
statusBusy: false,
removeBusy: false,
accessBusy: false,
showAccess: false,
});
@ -29,8 +30,17 @@ export function useAccountItem(token, item, remove) {
const actions = {
setAccessLink: async () => {
let access = await addAccountAccess(token, item.accountId);
updateState({ accessToken: access, showAccess: true });
if (!state.accessBusy) {
updateState({ accessBusy: true });
try {
let access = await addAccountAccess(token, item.accountId);
updateState({ accessToken: access, showAccess: true });
}
catch (err) {
window.alert(err);
}
updateState({ accessBusy: false });
}
},
setShowAccess: (showAccess) => {
updateState({ showAccess });

View File

@ -1,6 +1,6 @@
import { DashboardWrapper, SettingsButton, AddButton, SettingsLayout } from './Dashboard.styled';
import { DashboardWrapper, SettingsButton, AddButton, SettingsLayout, CreateLayout } from './Dashboard.styled';
import { Tooltip, Button, Modal, Input, InputNumber, Space, List } from 'antd';
import { SettingOutlined, UserAddOutlined, LogoutOutlined, ReloadOutlined } from '@ant-design/icons';
import { SettingOutlined, CopyOutlined, UserAddOutlined, LogoutOutlined, ReloadOutlined } from '@ant-design/icons';
import { useDashboard } from './useDashboard.hook';
import { AccountItem } from './AccountItem/AccountItem';
@ -8,6 +8,14 @@ export function Dashboard({ token, config, logout }) {
const { state, actions } = useDashboard(token, config);
const onClipboard = (value) => {
navigator.clipboard.writeText(value);
};
const createLink = () => {
return window.location.origin + '/#/create?add=' + state.createToken;
};
return (
<DashboardWrapper>
@ -34,7 +42,8 @@ export function Dashboard({ token, config, logout }) {
</div>
<div class="add">
<Tooltip placement="topRight" title="Create Account Link">
<AddButton type="text" size="large" icon={<UserAddOutlined />}></AddButton>
<AddButton type="text" size="large" icon={<UserAddOutlined />}
loading={state.createBusy} onClick={() => actions.setCreateLink()}></AddButton>
</Tooltip>
</div>
</div>
@ -60,13 +69,22 @@ export function Dashboard({ token, config, logout }) {
value={state.host} />
</div>
<div class="storage">
<div>Account Storage (GB):&nbsp;</div>
<div>Storage Limit (GB) / Account:&nbsp;</div>
<InputNumber defaultValue={8} onChange={(e) => actions.setStorage(e)}
placeholder="0 for unrestricted" value={state.storage} />
</div>
</SettingsLayout>
</Modal>
<Modal title="Create Account Link" visible={state.showCreate} centered width="fitContent"
footer={[ <Button type="primary" onClick={() => actions.setShowCreate(false)}>OK</Button> ]}
onCancel={() => actions.setShowCreate(false)}>
<CreateLayout>
<div>{createLink()}</div>
<Button icon={<CopyOutlined />} size="small"
onClick={() => onClipboard(createLink())}
/>
</CreateLayout>
</Modal>
</DashboardWrapper>
);
}

View File

@ -84,3 +84,7 @@ export const SettingsLayout = styled(Space)`
align-items: center;
}
`;
export const CreateLayout = styled(Space)`
white-space: nowrap;
`

View File

@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { setNodeConfig } from 'api/setNodeConfig';
import { getNodeAccounts } from 'api/getNodeAccounts';
import { removeAccount } from 'api/removeAccount';
import { addAccountCreate } from 'api/addAccountCreate';
export function useDashboard(token, config) {
@ -12,6 +13,8 @@ export function useDashboard(token, config) {
busy: false,
loading: false,
accounts: [],
createBusy: false,
showCreate: false,
});
const updateState = (value) => {
@ -19,6 +22,22 @@ export function useDashboard(token, config) {
}
const actions = {
setCreateLink: async () => {
if (!state.createBusy) {
updateState({ createBusy: true });
try {
let create = await addAccountCreate(token)
updateState({ createToken: create, showCreate: true });
}
catch (err) {
window.alert(err);
}
updateState({ createBusy: false });
}
},
setShowCreate: (showCreate) => {
updateState({ showCreate });
},
removeAccount: async (accountId) => {
await removeAccount(token, accountId);
actions.getAccounts();

View File

@ -1,6 +1,6 @@
import { useContext, useState, useEffect, useRef } from 'react';
import { AppContext } from 'context/AppContext';
import { useNavigate } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom";
export function useCreate() {
const [checked, setChecked] = useState(true)
@ -10,10 +10,12 @@ export function useCreate() {
confirmed: '',
conflict: '',
spinning: false,
token: null,
});
const navigate = useNavigate();
const app = useContext(AppContext);
const { search } = useLocation();
const debounce = useRef(null)
const actions = {
@ -41,7 +43,7 @@ export function useCreate() {
if (!state.spinning) {
actions.updateState({ spinning: true })
try {
await app.actions.create(state.username, state.password)
await app.actions.create(state.username, state.password, state.token)
}
catch (err) {
window.alert(err);
@ -64,7 +66,7 @@ export function useCreate() {
actions.updateState({ conflict: '' })
}
else {
let valid = await app.actions.username(name)
let valid = await app.actions.username(name, state.token)
setChecked(true)
if (!valid) {
actions.updateState({ conflict: 'not available' })
@ -82,8 +84,12 @@ export function useCreate() {
if (app.state.access === 'user') {
navigate('/user')
}
if (app.state.access === 'admin') {
navigate('/admin')
else {
let params = new URLSearchParams(search);
let token = params.get("add");
if (token) {
actions.updateState({ token });
}
}
}
}

View File

@ -43,10 +43,16 @@ export function ChannelLabel({ item }) {
}
if (item?.data?.channelDetail?.data) {
let data = JSON.parse(item.data.channelDetail.data);
if (data.subject != '' && data.subject != null) {
setSubject(data.subject);
return
try {
let data = JSON.parse(item.data.channelDetail.data);
if (data.subject != '' && data.subject != null) {
setSubject(data.subject);
return
}
}
catch (err) {
console.log(err);
setSubject(null);
}
}
setSubject(contacts.join(', '));

View File

@ -0,0 +1,15 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
var base64 = require('base-64');
export async function addAccount(username, password, token) {
let access = "";
if (token) {
access = `?token=${token}`
}
let headers = new Headers()
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
let profile = await fetchWithTimeout(`/account/profile${access}`, { method: 'POST', headers: headers })
checkResponse(profile);
return await profile.json()
}

View File

@ -0,0 +1,8 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addAccountCreate(token) {
let access = await fetchWithTimeout(`/admin/accounts?token=${token}`, { method: 'POST' })
checkResponse(access);
return await access.json()
}

View File

@ -1,7 +1,11 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getUsername(name) {
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name), { method: 'GET' })
export async function getUsername(name, token) {
let access = "";
if (token) {
access = `&token=${token}`
}
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name) + access, { method: 'GET' })
checkResponse(available)
return await available.json()
}

View File

@ -21,12 +21,6 @@ export async function getAvailable() {
return await available.json()
}
export async function getUsername(name) {
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name), { method: 'GET', timeout: FETCH_TIMEOUT })
checkResponse(available)
return await available.json()
}
export async function setLogin(username, password) {
let headers = new Headers()
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

View File

@ -1,7 +1,9 @@
import { useEffect, useState, useRef, useContext } from 'react';
import { useNavigate, useLocation, useParams } from "react-router-dom";
import { getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
import { getAvailable, setLogin } from './fetchUtil';
import { setAccountAccess } from 'api/setAccountAccess';
import { addAccount } from 'api/addAccount';
import { getUsername } from 'api/getUsername';
import { AccountContext } from './AccountContext';
import { ProfileContext } from './ProfileContext';
import { ArticleContext } from './ArticleContext';
@ -9,8 +11,8 @@ import { GroupContext } from './GroupContext';
import { CardContext } from './CardContext';
import { ChannelContext } from './ChannelContext';
async function appCreate(username, password, updateState, setWebsocket) {
await createAccount(username, password);
async function appCreate(username, password, token, updateState, setWebsocket) {
await addAccount(username, password, token);
let access = await setLogin(username, password)
updateState({ token: access, access: 'user' });
setWebsocket(access)
@ -95,8 +97,8 @@ export function useAppContext() {
login: async (username, password) => {
await appLogin(username, password, updateState, setWebsocket)
},
create: async (username, password) => {
await appCreate(username, password, updateState, setWebsocket)
create: async (username, password, token) => {
await appCreate(username, password, token, updateState, setWebsocket)
},
username: getUsername,
available: getAvailable,