diff --git a/net/server/internal/api_addChannelTopicAsset.go b/net/server/internal/api_addChannelTopicAsset.go
index b3a7352f..42220a33 100644
--- a/net/server/internal/api_addChannelTopicAsset.go
+++ b/net/server/internal/api_addChannelTopicAsset.go
@@ -172,7 +172,7 @@ func AddChannelTopicAsset(w http.ResponseWriter, r *http.Request) {
func isStorageFull(act *store.Account) (full bool, err error) {
- storage := getNumConfigValue(CONFIG_STORAGE, 0) * 1048576;
+ storage := getNumConfigValue(CONFIG_STORAGE, 0);
if storage == 0 {
return
}
diff --git a/net/server/internal/api_getNodeStatus.go b/net/server/internal/api_getNodeStatus.go
index 4b71b325..7a28c2bf 100644
--- a/net/server/internal/api_getNodeStatus.go
+++ b/net/server/internal/api_getNodeStatus.go
@@ -18,6 +18,6 @@ func GetNodeStatus(w http.ResponseWriter, r *http.Request) {
}
return
}
- WriteResponse(w, false);
+ WriteResponse(w, false)
}
diff --git a/net/server/internal/api_setNodeStatus.go b/net/server/internal/api_setNodeStatus.go
index 857b7493..2f01cf45 100644
--- a/net/server/internal/api_setNodeStatus.go
+++ b/net/server/internal/api_setNodeStatus.go
@@ -21,7 +21,7 @@ func SetNodeStatus(w http.ResponseWriter, r *http.Request) {
}
username, password, res := BasicCredentials(r);
- if res != nil {
+ if res != nil || username != "admin" {
LogMsg("invalid credenitals");
w.WriteHeader(http.StatusBadRequest)
return
diff --git a/net/server/internal/ucAccountConfig_test.go b/net/server/internal/ucAccountConfig_test.go
index 851ec5f0..7575cfdb 100644
--- a/net/server/internal/ucAccountConfig_test.go
+++ b/net/server/internal/ucAccountConfig_test.go
@@ -105,6 +105,7 @@ func TestAccountConfig(t *testing.T) {
assert.True(t, accountStatus.Searchable)
// add asset to topic
+PrintMsg("ADD TOPIC TEST");
assets = &[]Asset{}
pathParams = &map[string]string{ "channelId": channel.Id, "topicId": topic.Id }
assert.Error(t, ApiTestUpload(AddChannelTopicAsset, "POST",
diff --git a/net/web/src/Admin/Admin.jsx b/net/web/src/Admin/Admin.jsx
new file mode 100644
index 00000000..11ac293e
--- /dev/null
+++ b/net/web/src/Admin/Admin.jsx
@@ -0,0 +1,47 @@
+import React from 'react'
+import { Input, Button, Space } from 'antd';
+import { AdminWrapper, LoginWrapper, TokenInput } from './Admin.styled';
+import { useAdmin } from './useAdmin.hook';
+import { Dashboard } from './Dashboard/Dashboard';
+
+export function Admin() {
+
+ const { state, actions } = useAdmin()
+
+ if (state.unclaimed == null) {
+ return <>>
+ }
+
+ if (state.unclaimed) {
+ return (
+
+
+
+ actions.setToken(e.target.value)} />
+
+
+
+
+ );
+ }
+
+ if (!state.access) {
+ return (
+
+
+
+ actions.setToken(e.target.value)} />
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+ )
+}
+
diff --git a/net/web/src/Admin/Admin.styled.js b/net/web/src/Admin/Admin.styled.js
new file mode 100644
index 00000000..47fc356f
--- /dev/null
+++ b/net/web/src/Admin/Admin.styled.js
@@ -0,0 +1,47 @@
+import { Input } from 'antd';
+import styled from 'styled-components';
+
+export const AdminWrapper = styled.div`
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #8fbea7;
+ webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+
+ .dashboard {
+ width: 80%;
+ min-width: 400px;
+ max-width: 800px;
+ max-height: 80%;
+ background-color: #eeeeee;
+ border-radius: 4px;
+ }
+`;
+
+export const LoginWrapper = styled.div`
+ width: 100%;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .login {
+ padding: 8px;
+ display: flex;
+ flex-direction: row;
+ background-color: #eeeeee;
+ border-radius: 4px;
+ }
+`;
+
+export const TokenInput = styled(Input.Password)`
+ width: 300px;
+`;
diff --git a/net/web/src/Admin/Dashboard/Dashboard.jsx b/net/web/src/Admin/Dashboard/Dashboard.jsx
new file mode 100644
index 00000000..0be7d44e
--- /dev/null
+++ b/net/web/src/Admin/Dashboard/Dashboard.jsx
@@ -0,0 +1,4 @@
+export function Dashboard() {
+ return (
DASHBOARD
);
+}
+
diff --git a/net/web/src/Admin/useAdmin.hook.js b/net/web/src/Admin/useAdmin.hook.js
new file mode 100644
index 00000000..d6d543f4
--- /dev/null
+++ b/net/web/src/Admin/useAdmin.hook.js
@@ -0,0 +1,62 @@
+import { useContext, useState, useEffect } from 'react';
+import { getNodeStatus } from 'api/getNodeStatus';
+import { setNodeStatus } from 'api/setNodeStatus';
+import { getNodeConfig } from 'api/getNodeConfig';
+
+export function useAdmin() {
+
+ const [state, setState] = useState({
+ unclaimed: null,
+ access: null,
+ token: null,
+ busy: false,
+ });
+
+ const updateState = (value) => {
+ setState((s) => ({ ...s, ...value }));
+ }
+
+ const checkStatus = async () => {
+ try {
+ let status = await getNodeStatus();
+ updateState({ unclaimed: status });
+ }
+ catch(err) {
+ console.log(err);
+ window.alert(err);
+ }
+ }
+
+ useEffect(() => {
+ checkStatus();
+ }, []);
+
+
+ const actions = {
+ setToken: (value) => {
+ updateState({ token: value });
+ },
+ setAccess: async () => {
+ try {
+ await setNodeStatus(state.token);
+ updateState({ access: state.token, unclaimed: false });
+ }
+ catch(err) {
+ console.log(err);
+ window.alert(err);
+ }
+ },
+ getAccess: async () => {
+ try {
+ let config = await getNodeConfig(state.token);
+ updateState({ access: state.token, config });
+ }
+ catch(err) {
+ console.log(err);
+ window.alert(err);
+ }
+ },
+ };
+
+ return { state, actions };
+}
diff --git a/net/web/src/App.js b/net/web/src/App.js
index a5ddbf82..c7d34b5d 100644
--- a/net/web/src/App.js
+++ b/net/web/src/App.js
@@ -8,6 +8,7 @@ import { CardContextProvider } from 'context/CardContext';
import { ChannelContextProvider } from 'context/ChannelContext';
import { ConversationContextProvider } from 'context/ConversationContext';
import { Home } from './Home/Home';
+import { Admin } from './Admin/Admin';
import { Login } from './Login/Login';
import { Create } from './Create/Create';
import { User } from './User/User';
@@ -35,6 +36,7 @@ function App() {
} />
} />
+ } />
} />
}>
} />
diff --git a/net/web/src/api/getNodeConfig.js b/net/web/src/api/getNodeConfig.js
new file mode 100644
index 00000000..3005a989
--- /dev/null
+++ b/net/web/src/api/getNodeConfig.js
@@ -0,0 +1,11 @@
+import { checkResponse, fetchWithTimeout } from './fetchUtil';
+var base64 = require('base-64');
+
+export async function getNodeConfig(password) {
+ let headers = new Headers()
+ headers.append('Authorization', 'Basic ' + base64.encode("admin:" + password));
+ let config = await fetchWithTimeout(`/admin/config`, { method: 'GET', headers });
+ checkResponse(config);
+ return await config.json();
+}
+
diff --git a/net/web/src/api/getNodeStatus.js b/net/web/src/api/getNodeStatus.js
new file mode 100644
index 00000000..9232bf0a
--- /dev/null
+++ b/net/web/src/api/getNodeStatus.js
@@ -0,0 +1,8 @@
+import { checkResponse, fetchWithTimeout } from './fetchUtil';
+
+export async function getNodeStatus() {
+ let status = await fetchWithTimeout(`/admin/status`, { method: 'GET' });
+ checkResponse(status);
+ return await status.json();
+}
+
diff --git a/net/web/src/api/setNodeStatus.js b/net/web/src/api/setNodeStatus.js
new file mode 100644
index 00000000..9fffa313
--- /dev/null
+++ b/net/web/src/api/setNodeStatus.js
@@ -0,0 +1,10 @@
+import { checkResponse, fetchWithTimeout } from './fetchUtil';
+var base64 = require('base-64');
+
+export async function setNodeStatus(password) {
+ let headers = new Headers()
+ headers.append('Credentials', 'Basic ' + base64.encode("admin:" + password));
+ let status = await fetchWithTimeout(`/admin/status`, { method: 'PUT', headers });
+ checkResponse(status);
+}
+