mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
connecting websokcet
This commit is contained in:
parent
7e824d19b3
commit
f682d4c9d3
23
doc/api.oa3
23
doc/api.oa3
@ -293,7 +293,7 @@ paths:
|
|||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
parameters:
|
parameters:
|
||||||
- name: username
|
- name: name
|
||||||
in: query
|
in: query
|
||||||
description: username to check
|
description: username to check
|
||||||
required: true
|
required: true
|
||||||
@ -601,28 +601,7 @@ paths:
|
|||||||
- account
|
- account
|
||||||
description: Generate token to attach an app to the account. Access granted to account's username and password.
|
description: Generate token to attach an app to the account. Access granted to account's username and password.
|
||||||
operationId: add-account-app
|
operationId: add-account-app
|
||||||
security:
|
|
||||||
- basicAuth: []
|
- basicAuth: []
|
||||||
responses:
|
|
||||||
'201':
|
|
||||||
description: generated
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
'401':
|
|
||||||
description: invalid password
|
|
||||||
'410':
|
|
||||||
description: account disabled
|
|
||||||
'500':
|
|
||||||
description: internal server error
|
|
||||||
put:
|
|
||||||
tags:
|
|
||||||
- account
|
|
||||||
description: Apply the token to attach an app to the account. Access granted to valid attach token.
|
|
||||||
operationId: set-account-app
|
|
||||||
security:
|
|
||||||
- bearerAuth: []
|
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: generated
|
description: generated
|
||||||
|
@ -2,38 +2,57 @@ package databag
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"gorm.io/gorm"
|
||||||
"databag/internal/store"
|
"databag/internal/store"
|
||||||
"github.com/theckman/go-securerandom"
|
"github.com/theckman/go-securerandom"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddAccountApp(w http.ResponseWriter, r *http.Request) {
|
func AddAccountApp(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
account, err := AccountLogin(r)
|
account, res := AccountLogin(r)
|
||||||
if err != nil {
|
|
||||||
ErrResponse(w, http.StatusUnauthorized, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data, res := securerandom.Bytes(4)
|
|
||||||
if res != nil {
|
if res != nil {
|
||||||
ErrResponse(w, http.StatusInternalServerError, res)
|
ErrResponse(w, http.StatusUnauthorized, res)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
token := hex.EncodeToString(data)
|
|
||||||
|
|
||||||
accountToken := store.AccountToken{
|
// parse app data
|
||||||
AccountID: account.ID,
|
var appData AppData
|
||||||
TokenType: APP_TOKENATTACH,
|
if err := ParseRequest(r, w, &appData); err != nil {
|
||||||
Token: token,
|
ErrResponse(w, http.StatusBadRequest, err)
|
||||||
Expires: time.Now().Unix() + APP_ATTACHEXPIRE,
|
return
|
||||||
}
|
}
|
||||||
if err := store.DB.Create(&accountToken).Error; err != nil {
|
|
||||||
|
// gernate app token
|
||||||
|
data, err := securerandom.Bytes(APP_TOKENSIZE)
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
access := hex.EncodeToString(data)
|
||||||
|
|
||||||
|
// create app entry
|
||||||
|
app := store.App {
|
||||||
|
AccountID: account.Guid,
|
||||||
|
Name: appData.Name,
|
||||||
|
Description: appData.Description,
|
||||||
|
Image: appData.Image,
|
||||||
|
Url: appData.Url,
|
||||||
|
Token: access,
|
||||||
|
};
|
||||||
|
|
||||||
|
// save app and delete token
|
||||||
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := store.DB.Create(&app).Error; res != nil {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
});
|
||||||
|
if err != nil {
|
||||||
ErrResponse(w, http.StatusInternalServerError, err)
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteResponse(w, token)
|
WriteResponse(w, account.Guid + "." + access)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ func GetAccountUsername(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
username := r.URL.Query().Get("username")
|
username := r.URL.Query().Get("name")
|
||||||
if username == "" {
|
if username == "" {
|
||||||
ErrResponse(w, http.StatusBadRequest, errors.New("specify a username"))
|
ErrResponse(w, http.StatusBadRequest, errors.New("specify a username"))
|
||||||
return
|
return
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
package databag
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"encoding/hex"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"databag/internal/store"
|
|
||||||
"github.com/theckman/go-securerandom"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SetAccountApp(w http.ResponseWriter, r *http.Request) {
|
|
||||||
|
|
||||||
token, res := BearerAccountToken(r);
|
|
||||||
if res != nil || token.TokenType != APP_TOKENATTACH {
|
|
||||||
ErrResponse(w, http.StatusUnauthorized, res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse app data
|
|
||||||
var appData AppData
|
|
||||||
if res = ParseRequest(r, w, &appData); res != nil {
|
|
||||||
ErrResponse(w, http.StatusBadRequest, res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// gernate app token
|
|
||||||
data, err := securerandom.Bytes(APP_TOKENSIZE)
|
|
||||||
if err != nil {
|
|
||||||
ErrResponse(w, http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
access := hex.EncodeToString(data)
|
|
||||||
|
|
||||||
// create app entry
|
|
||||||
app := store.App {
|
|
||||||
AccountID: token.Account.Guid,
|
|
||||||
Name: appData.Name,
|
|
||||||
Description: appData.Description,
|
|
||||||
Image: appData.Image,
|
|
||||||
Url: appData.Url,
|
|
||||||
Token: access,
|
|
||||||
};
|
|
||||||
|
|
||||||
// save app and delete token
|
|
||||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
|
||||||
if res := store.DB.Create(&app).Error; res != nil {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
if res := store.DB.Delete(token).Error; res != nil {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return nil;
|
|
||||||
});
|
|
||||||
if err != nil {
|
|
||||||
ErrResponse(w, http.StatusInternalServerError, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteResponse(w, access)
|
|
||||||
}
|
|
@ -50,6 +50,7 @@ func ErrResponse(w http.ResponseWriter, code int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ErrMsg(err error) {
|
func ErrMsg(err error) {
|
||||||
|
PrintMsg("IN ERR MSG")
|
||||||
if !hideLog && err != nil {
|
if !hideLog && err != nil {
|
||||||
_, file, line, _ := runtime.Caller(1)
|
_, file, line, _ := runtime.Caller(1)
|
||||||
p, _ := os.Getwd()
|
p, _ := os.Getwd()
|
||||||
|
@ -146,13 +146,6 @@ var routes = Routes{
|
|||||||
RemoveAccountApp,
|
RemoveAccountApp,
|
||||||
},
|
},
|
||||||
|
|
||||||
Route{
|
|
||||||
"SetAccountApp",
|
|
||||||
strings.ToUpper("Put"),
|
|
||||||
"/account/apps",
|
|
||||||
SetAccountApp,
|
|
||||||
},
|
|
||||||
|
|
||||||
Route{
|
Route{
|
||||||
"SetAccountAuthentication",
|
"SetAccountAuthentication",
|
||||||
strings.ToUpper("Put"),
|
strings.ToUpper("Put"),
|
||||||
|
@ -610,7 +610,7 @@ func AddTestAccount(username string) (guid string, token string, err error) {
|
|||||||
guid = profile.Guid
|
guid = profile.Guid
|
||||||
|
|
||||||
// acquire new token for attaching app
|
// acquire new token for attaching app
|
||||||
if r, w, err = NewRequest("POST", "/account/apps", nil); err != nil {
|
if r, w, err = NewRequest("POST", "/account/apps", &app); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
SetBasicAuth(r, login);
|
SetBasicAuth(r, login);
|
||||||
@ -618,17 +618,7 @@ func AddTestAccount(username string) (guid string, token string, err error) {
|
|||||||
if err = ReadResponse(w, &access); err != nil {
|
if err = ReadResponse(w, &access); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
token = access
|
||||||
// attach app with token
|
|
||||||
if r, w, err = NewRequest("PUT", "/account/apps", &app); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SetBearerAuth(r, access)
|
|
||||||
SetAccountApp(w, r)
|
|
||||||
if err = ReadResponse(w, &access); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
token = guid + "." + access
|
|
||||||
|
|
||||||
// authorize claim
|
// authorize claim
|
||||||
if r, w, err = NewRequest("PUT", "/authorize", "1234abcd"); err != nil {
|
if r, w, err = NewRequest("PUT", "/authorize", "1234abcd"); err != nil {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"@testing-library/react": "^12.0.0",
|
"@testing-library/react": "^12.0.0",
|
||||||
"@testing-library/user-event": "^13.2.1",
|
"@testing-library/user-event": "^13.2.1",
|
||||||
"antd": "^4.19.1",
|
"antd": "^4.19.1",
|
||||||
|
"base-64": "^1.0.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-scripts": "5.0.0",
|
"react-scripts": "5.0.0",
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect, useRef } from 'react'
|
||||||
import login from './login.png';
|
import login from './login.png';
|
||||||
import { Input, Button } from 'antd';
|
import { Input, Button } from 'antd';
|
||||||
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
import { UserOutlined, LockOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import 'antd/dist/antd.css';
|
import 'antd/dist/antd.css';
|
||||||
|
|
||||||
|
var base64 = require('base-64');
|
||||||
|
|
||||||
const FETCH_TIMEOUT = 15000;
|
const FETCH_TIMEOUT = 15000;
|
||||||
|
|
||||||
function checkResponse(response) {
|
function checkResponse(response) {
|
||||||
@ -21,60 +22,222 @@ async function fetchWithTimeout(url, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getAvailable() {
|
async function getAvailable() {
|
||||||
let available = await fetchWithTimeout("/account/available", { method: 'GET', timeout: FETCH_TIMEOUT } );
|
let available = await fetchWithTimeout("/account/available", { method: 'GET', timeout: FETCH_TIMEOUT })
|
||||||
checkResponse(available);
|
checkResponse(available)
|
||||||
return await available.json()
|
return await available.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUsername(name: string) {
|
||||||
|
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name), { method: 'GET', timeout: FETCH_TIMEOUT })
|
||||||
|
checkResponse(available)
|
||||||
|
return await available.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setLogin(username: string, password: string) {
|
||||||
|
let headers = new Headers()
|
||||||
|
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
|
||||||
|
let app = { Name: "indicom", Description: "decentralized communication" }
|
||||||
|
let login = await fetchWithTimeout('/account/apps', { method: 'POST', timeout: FETCH_TIMEOUT, body: JSON.stringify(app), headers: headers })
|
||||||
|
checkResponse(login)
|
||||||
|
return await login.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createAccount(username: string, password: string) {
|
||||||
|
let headers = new Headers()
|
||||||
|
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
|
||||||
|
let profile = await fetchWithTimeout("/account/profile", { method: 'POST', timeout: FETCH_TIMEOUT, headers: headers })
|
||||||
|
checkResponse(profile);
|
||||||
|
return await profile.json()
|
||||||
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [available, setAvailable] = useState(0)
|
const [available, setAvailable] = useState(false)
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
const [password, setPassword] = useState('')
|
const [password, setPassword] = useState('')
|
||||||
|
const [confirmed, setConfirmed] = useState('')
|
||||||
|
const [mode, setMode] = useState('login')
|
||||||
|
const [creatable, setCreatable] = useState(false)
|
||||||
|
const [conflict, setConflict] = useState('')
|
||||||
|
const [token, setToken] = useState('')
|
||||||
|
const debounce = useRef(null)
|
||||||
|
const ws = useRef(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
getAvailable().then(a => {
|
getAvailable().then(a => {
|
||||||
setAvailable(a)
|
setAvailable(a > 0)
|
||||||
console.log(a)
|
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const Create = () => {
|
const usernameSet = (name) => {
|
||||||
if (available > 0) {
|
setCreatable(false)
|
||||||
return <Button type="link" onClick={onCreate} style={{ marginTop: '4px', color: '#000044' }}>Create Account</Button>
|
setUsername(name)
|
||||||
|
clearTimeout(debounce.current)
|
||||||
|
debounce.current = setTimeout(async () => {
|
||||||
|
let valid = await getUsername(name)
|
||||||
|
setCreatable(valid)
|
||||||
|
if (!valid) {
|
||||||
|
setConflict('not available')
|
||||||
|
} else {
|
||||||
|
setConflict('')
|
||||||
|
}
|
||||||
|
setCreatable(await getUsername(name))
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectStatus = (access: string) => {
|
||||||
|
ws.current = new WebSocket("wss://" + window.location.host + "/status");
|
||||||
|
ws.current.onmessage = (ev) => {
|
||||||
|
console.log(ev)
|
||||||
|
}
|
||||||
|
ws.current.onclose = () => {
|
||||||
|
console.log('ws close')
|
||||||
|
setTimeout(() => {
|
||||||
|
if (ws.current != null) {
|
||||||
|
ws.current.onmessage = () => {}
|
||||||
|
ws.current.onclose = () => {}
|
||||||
|
ws.current.onopen = () => {}
|
||||||
|
ws.current.onerror = () => {}
|
||||||
|
connectStatus(access)
|
||||||
|
}
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
ws.current.onopen = () => {
|
||||||
|
ws.current.send(JSON.stringify({ AppToken: access }))
|
||||||
|
}
|
||||||
|
ws.current.error = () => {
|
||||||
|
console.log('ws error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Logout = () => {
|
||||||
|
if (mode === 'logout') {
|
||||||
|
return <Button type="primary" onClick={onLogout} style={{ alignSelf: 'center', marginTop: '16px', width: '33%' }}>Sign Out</Button>
|
||||||
}
|
}
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
const onLogin = () => {
|
const Link = () => {
|
||||||
console.log(username)
|
if (mode === 'create') {
|
||||||
console.log(password)
|
return <Button type="link" onClick={() => setMode('login')} disabled={!available} style={{ marginTop: '4px' }}>Account Sign In</Button>
|
||||||
|
}
|
||||||
|
if (mode === 'login') {
|
||||||
|
return <Button type="link" onClick={() => setMode('create')} disabled={!available} style={{ marginTop: '4px' }}>Create Account</Button>
|
||||||
|
}
|
||||||
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
const onCreate = () => {
|
const canLogin = () => {
|
||||||
console.log("create account")
|
return username !== '' && password !== ''
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const canCreate = () => {
|
||||||
<div style={{ width: '100%', height: '100vh', backgroundColor: '#8fbea7' }}>
|
return username !== '' && password !== '' && confirmed === password && creatable
|
||||||
<img src={login} style={{ position: 'absolute', width: '33%', bottom: 0, right: 0 }}/>
|
}
|
||||||
<div style={{ position: 'absolute', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', top: 0, left: 0, width: '100%', height: '67%' }}>
|
|
||||||
<div style={{ backgroundColor: '#ffffff', display: 'flex', flexDirection: 'column', padding: '16px', borderRadius: '8px', width: '500px' }}>
|
const onLogin = async () => {
|
||||||
<div style={{ textAlign: 'center', fontSize: '24px', fontWeight: 'bold', color: '#555555' }}>indicom</div>
|
try {
|
||||||
<div style={{ fontSize: '12px', display: 'flex', borderBottom: '1px solid black', color: '#444444', paddingLeft: '16px', paddingRight: '16px' }}>
|
let access = await setLogin(username, password)
|
||||||
<span style={{ textAlign: 'center', width: '100%' }}>Communication for the Decentralized Web</span>
|
connectStatus(access)
|
||||||
|
setMode('logout')
|
||||||
|
console.log(access)
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
window.alert("failed to sign into account")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCreate = async () => {
|
||||||
|
try {
|
||||||
|
let profile = await createAccount(username, password)
|
||||||
|
setMode('created')
|
||||||
|
try {
|
||||||
|
let access = await setLogin(username, password)
|
||||||
|
connectStatus(access)
|
||||||
|
setMode('logout')
|
||||||
|
console.log(access)
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
window.alert("failed to sign into account")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
window.alert("failed to create account")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onLogout = () => {
|
||||||
|
ws.current.onclose = () => {}
|
||||||
|
ws.current.close(1000, "bye")
|
||||||
|
setMode('login')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === 'login') {
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%', height: '100vh', backgroundColor: '#8fbea7' }}>
|
||||||
|
<img src={login} alt="" style={{ position: 'absolute', width: '33%', bottom: 0, right: 0 }}/>
|
||||||
|
<div style={{ position: 'absolute', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', top: 0, left: 0, width: '100%', height: '67%' }}>
|
||||||
|
<div style={{ backgroundColor: '#ffffff', display: 'flex', flexDirection: 'column', padding: '16px', borderRadius: '8px', width: '500px' }}>
|
||||||
|
<div style={{ textAlign: 'center', fontSize: '24px', fontWeight: 'bold', color: '#555555' }}>indicom</div>
|
||||||
|
<div style={{ fontSize: '12px', display: 'flex', borderBottom: '1px solid black', color: '#444444', paddingLeft: '16px', paddingRight: '16px' }}>
|
||||||
|
<span style={{ textAlign: 'center', width: '100%' }}>Communication for the Decentralized Web</span>
|
||||||
|
</div>
|
||||||
|
<Input size="large" spellCheck="false" onChange={(e) => usernameSet(e.target.value)} value={username} placeholder="username" prefix={<UserOutlined />} style={{ marginTop: '16px' }} />
|
||||||
|
<Input.Password size="large" onChange={(e) => setPassword(e.target.value)} value={password} placeholder="password" prefix={<LockOutlined />} style={{ marginTop: '16px' }} />
|
||||||
|
<Button type="primary" onClick={onLogin} disabled={!canLogin()} style={{ alignSelf: 'center', marginTop: '16px', width: '33%' }}>Sign In</Button>
|
||||||
</div>
|
</div>
|
||||||
<Input size="large" onChange={(e) => setUsername(e.target.value)} placeholder="username" prefix={<UserOutlined />} style={{ marginTop: '16px' }} />
|
<Link />
|
||||||
<Input.Password size="large" onChange={(e) => setPassword(e.target.value)} placeholder="password" prefix={<LockOutlined />} style={{ marginTop: '16px' }} />
|
|
||||||
<Button type="primary" onClick={onLogin} style={{ alignSelf: 'center', marginTop: '16px', width: '33%' }}>Sign In</Button>
|
|
||||||
</div>
|
</div>
|
||||||
<Create />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
);
|
}
|
||||||
|
if (mode === 'create') {
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%', height: '100vh', backgroundColor: '#8fbea7' }}>
|
||||||
|
<img src={login} alt="" style={{ position: 'absolute', width: '33%', bottom: 0, right: 0 }}/>
|
||||||
|
<div style={{ position: 'absolute', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', top: 0, left: 0, width: '100%', height: '67%' }}>
|
||||||
|
<div style={{ backgroundColor: '#ffffff', display: 'flex', flexDirection: 'column', padding: '16px', borderRadius: '8px', width: '500px' }}>
|
||||||
|
<div style={{ textAlign: 'center', fontSize: '24px', fontWeight: 'bold', color: '#555555' }}>indicom</div>
|
||||||
|
<div style={{ fontSize: '12px', display: 'flex', borderBottom: '1px solid black', color: '#444444', paddingLeft: '16px', paddingRight: '16px' }}>
|
||||||
|
<span style={{ textAlign: 'center', width: '100%' }}>Communication for the Decentralized Web</span>
|
||||||
|
</div>
|
||||||
|
<Input size="large" spellCheck="false" addonAfter={conflict} onChange={(e) => usernameSet(e.target.value)} value={username} placeholder="username" prefix={<UserOutlined />} style={{ marginTop: '16px' }} />
|
||||||
|
<Input.Password size="large" onChange={(e) => setPassword(e.target.value)} value={password} placeholder="password" prefix={<LockOutlined />} style={{ marginTop: '16px' }} />
|
||||||
|
<Input.Password size="large" onChange={(e) => setConfirmed(e.target.value)} value={confirmed} placeholder="confirm password" prefix={<LockOutlined />} style={{ marginTop: '16px' }} />
|
||||||
|
<Button type="primary" onClick={onCreate} disabled={!canCreate()} style={{ alignSelf: 'center', marginTop: '16px', width: '33%' }}>Create Account</Button>
|
||||||
|
</div>
|
||||||
|
<Link />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (mode === 'logout') {
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%', height: '100vh', backgroundColor: '#8fbea7' }}>
|
||||||
|
<img src={login} alt="" style={{ position: 'absolute', width: '33%', bottom: 0, right: 0 }}/>
|
||||||
|
<div style={{ position: 'absolute', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', top: 0, left: 0, width: '100%', height: '67%' }}>
|
||||||
|
<div style={{ backgroundColor: '#ffffff', display: 'flex', flexDirection: 'column', padding: '16px', borderRadius: '8px', width: '500px' }}>
|
||||||
|
<div style={{ textAlign: 'center', fontSize: '24px', fontWeight: 'bold', color: '#555555' }}>indicom</div>
|
||||||
|
<div style={{ fontSize: '12px', display: 'flex', borderBottom: '1px solid black', color: '#444444', paddingLeft: '16px', paddingRight: '16px' }}>
|
||||||
|
<span style={{ textAlign: 'center', width: '100%' }}>Communication for the Decentralized Web</span>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" onClick={onLogout} style={{ alignSelf: 'center', marginTop: '16px', width: '33%' }}>Sign Out</Button>
|
||||||
|
</div>
|
||||||
|
<Link />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%', height: '100vh', backgroundColor: '#8fbea7' }}>
|
||||||
|
<img src={login} alt="" style={{ position: 'absolute', width: '33%', bottom: 0, right: 0 }}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
2411
net/web/yarn.lock
2411
net/web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user