mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
adding login reset
This commit is contained in:
parent
c8030d27e6
commit
c144356252
@ -68,6 +68,8 @@ func AddChannelTopicAsset(w http.ResponseWriter, r *http.Request) {
|
|||||||
garbageSync.Lock()
|
garbageSync.Lock()
|
||||||
defer garbageSync.Unlock()
|
defer garbageSync.Unlock()
|
||||||
|
|
||||||
|
PrintMsg("SAVE NEW ASSET");
|
||||||
|
|
||||||
// save new file
|
// save new file
|
||||||
id := uuid.New().String()
|
id := uuid.New().String()
|
||||||
path := getStrConfigValue(CONFIG_ASSETPATH, APP_DEFAULTPATH) + "/" + channelSlot.Account.Guid + "/" + id
|
path := getStrConfigValue(CONFIG_ASSETPATH, APP_DEFAULTPATH) + "/" + channelSlot.Account.Guid + "/" + id
|
||||||
|
46
net/server/internal/api_setAccountLogin.go
Normal file
46
net/server/internal/api_setAccountLogin.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package databag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"databag/internal/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetAccountLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
account, code, err := ParamAgentToken(r, true);
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, code, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
username, password, ret := BasicCredentials(r);
|
||||||
|
if ret != nil {
|
||||||
|
ErrResponse(w, http.StatusUnauthorized, ret)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if res := tx.Model(&account).Update("account_revision", account.AccountRevision + 1).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Model(&account).Update("profile_revision", account.AccountRevision + 1).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Model(&account).Update("Username", username).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
if res := tx.Model(&account).Update("Password", password).Error; res != nil {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ErrResponse(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
SetStatus(account)
|
||||||
|
WriteResponse(w, nil)
|
||||||
|
}
|
||||||
|
|
@ -165,6 +165,13 @@ var routes = Routes{
|
|||||||
SetAccountNode,
|
SetAccountNode,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Route{
|
||||||
|
"SetAccountLogin",
|
||||||
|
strings.ToUpper("Put"),
|
||||||
|
"/account/login",
|
||||||
|
SetAccountLogin,
|
||||||
|
},
|
||||||
|
|
||||||
Route{
|
Route{
|
||||||
"SetAccountSerchable",
|
"SetAccountSerchable",
|
||||||
strings.ToUpper("Put"),
|
strings.ToUpper("Put"),
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { Avatar, Image } from 'antd';
|
import { Avatar, Space, Image, Modal, Form, Input } from 'antd';
|
||||||
import React from 'react'
|
import React, { useState } from 'react'
|
||||||
import { IdentityWrapper, IdentityDropdown, MenuWrapper } from './Identity.styled';
|
import { IdentityWrapper, IdentityDropdown, MenuWrapper } from './Identity.styled';
|
||||||
import { RightOutlined, EditOutlined, UserOutlined } from '@ant-design/icons';
|
import { RightOutlined, EditOutlined, UserOutlined, LockOutlined } from '@ant-design/icons';
|
||||||
import { useIdentity } from './useIdentity.hook';
|
import { useIdentity } from './useIdentity.hook';
|
||||||
import { Menu, Dropdown } from 'antd';
|
import { Menu, Dropdown } from 'antd';
|
||||||
import { Logo } from '../../../Logo/Logo';
|
import { Logo } from '../../../Logo/Logo';
|
||||||
|
|
||||||
export function Identity() {
|
export function Identity() {
|
||||||
|
|
||||||
|
const [ showLogin, setShowLogin ] = useState(false);
|
||||||
const { state, actions } = useIdentity()
|
const { state, actions } = useIdentity()
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
@ -16,7 +17,7 @@ export function Identity() {
|
|||||||
<div onClick={() => actions.editProfile()}>Edit Profile</div>
|
<div onClick={() => actions.editProfile()}>Edit Profile</div>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="1">
|
<Menu.Item key="1">
|
||||||
<div>Change Login</div>
|
<div onClick={() => setShowLogin(true)}>Change Login</div>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="2">
|
<Menu.Item key="2">
|
||||||
<div onClick={() => actions.logout()}>Sign Out</div>
|
<div onClick={() => actions.logout()}>Sign Out</div>
|
||||||
@ -24,6 +25,11 @@ export function Identity() {
|
|||||||
</MenuWrapper>
|
</MenuWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onChangeLogin = () => {
|
||||||
|
let saved = actions.setLogin();
|
||||||
|
setShowLogin(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IdentityWrapper>
|
<IdentityWrapper>
|
||||||
<IdentityDropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="rightTop">
|
<IdentityDropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="rightTop">
|
||||||
@ -38,6 +44,23 @@ export function Identity() {
|
|||||||
<RightOutlined />
|
<RightOutlined />
|
||||||
</div>
|
</div>
|
||||||
</IdentityDropdown>
|
</IdentityDropdown>
|
||||||
|
<Modal title="Change Login" visible={showLogin} centered okText="Save"
|
||||||
|
onOk={() => onChangeLogin()} onCancel={() => setShowLogin(false)}>
|
||||||
|
|
||||||
|
<Space direction="vertical" style={{ width: '100%' }}>
|
||||||
|
<Input size="large" spelleCheck="false" placeholder="Username" prefix={<UserOutlined />}
|
||||||
|
onChange={(e) => actions.setUsername(e.target.value)} defaultValue={state.handle}
|
||||||
|
addonAfter={state.usernameStatus} />
|
||||||
|
|
||||||
|
<Input.Password size="large" spelleCheck="false" placeholder="Password" prefix={<LockOutlined />}
|
||||||
|
onChange={(e) => actions.setPassword(e.target.value)}
|
||||||
|
addonAfter={state.passwordStatus} />
|
||||||
|
|
||||||
|
<Input.Password size="large" spelleCheck="false" placeholder="Confirm Password" prefix={<LockOutlined />}
|
||||||
|
onChange={(e) => actions.setConfirm(e.target.value)}
|
||||||
|
addonAfter={state.confirmStatus} />
|
||||||
|
</Space>
|
||||||
|
</Modal>
|
||||||
</IdentityWrapper>
|
</IdentityWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { useContext, useState, useEffect } from 'react';
|
import { useContext, useState, useRef, useEffect } from 'react';
|
||||||
import { AppContext } from 'context/AppContext';
|
import { AppContext } from 'context/AppContext';
|
||||||
import { ProfileContext } from 'context/ProfileContext';
|
import { ProfileContext } from 'context/ProfileContext';
|
||||||
|
import { AccountContext } from 'context/AccountContext';
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { getUsername } from 'api/getUsername';
|
||||||
|
|
||||||
export function useIdentity() {
|
export function useIdentity() {
|
||||||
|
|
||||||
@ -11,11 +13,21 @@ export function useIdentity() {
|
|||||||
domain: '',
|
domain: '',
|
||||||
imageUrl: null,
|
imageUrl: null,
|
||||||
image: null,
|
image: null,
|
||||||
|
|
||||||
|
username: null,
|
||||||
|
usernameStatus: null,
|
||||||
|
password: null,
|
||||||
|
passwordStatus: null,
|
||||||
|
confirm: null,
|
||||||
|
confirmStatus: null,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const profile = useContext(ProfileContext);
|
const profile = useContext(ProfileContext);
|
||||||
|
const account = useContext(AccountContext);
|
||||||
const app = useContext(AppContext);
|
const app = useContext(AppContext);
|
||||||
|
const debounce = useRef(null);
|
||||||
|
|
||||||
const updateState = (value) => {
|
const updateState = (value) => {
|
||||||
setState((s) => ({ ...s, ...value }));
|
setState((s) => ({ ...s, ...value }));
|
||||||
@ -31,7 +43,56 @@ export function useIdentity() {
|
|||||||
},
|
},
|
||||||
editProfile: () => {
|
editProfile: () => {
|
||||||
navigate('/user/profile');
|
navigate('/user/profile');
|
||||||
}
|
},
|
||||||
|
setUsername: (value) => {
|
||||||
|
if (debounce.current) {
|
||||||
|
clearTimeout(debounce.current);
|
||||||
|
}
|
||||||
|
updateState({ username: value });
|
||||||
|
if (state.handle.toLowerCase() == value.toLowerCase() || value == null || value == '') {
|
||||||
|
updateState({ usernameStatus: null });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debounce.current = setTimeout(async () => {
|
||||||
|
let available = await getUsername(value);
|
||||||
|
if (available) {
|
||||||
|
updateState({ usernameStatus: null });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateState({ usernameStatus: 'not available' });
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
},
|
||||||
|
setPassword: (value) => {
|
||||||
|
updateState({ password: value });
|
||||||
|
},
|
||||||
|
setConfirm: (value) => {
|
||||||
|
updateState({ confirm: value });
|
||||||
|
},
|
||||||
|
setLogin: async () => {
|
||||||
|
if (state.username == null || state.username == '') {
|
||||||
|
updateState({ usernameStatus: 'username required' });
|
||||||
|
throw 'username required';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateState({ usernameStatus: null });
|
||||||
|
}
|
||||||
|
if (state.password == null || state.password == '') {
|
||||||
|
updateState({ passwordStatus: 'password required' });
|
||||||
|
throw 'password required';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateState({ passwordStatus: null });
|
||||||
|
}
|
||||||
|
if (state.confirm != state.password) {
|
||||||
|
updateState({ confirmStatus: 'password mismatch' });
|
||||||
|
throw 'password mismatch';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateState({ confirmStatus: null });
|
||||||
|
}
|
||||||
|
await account.actions.setLogin(state.username, state.password);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -47,6 +108,7 @@ export function useIdentity() {
|
|||||||
updateState({ image: identity.image });
|
updateState({ image: identity.image });
|
||||||
updateState({ name: identity.name });
|
updateState({ name: identity.name });
|
||||||
updateState({ handle: identity.handle });
|
updateState({ handle: identity.handle });
|
||||||
|
updateState({ username: identity.handle });
|
||||||
updateState({ domain: identity.node });
|
updateState({ domain: identity.node });
|
||||||
}
|
}
|
||||||
}, [profile])
|
}, [profile])
|
||||||
|
8
net/web/src/api/getUsername.js
Normal file
8
net/web/src/api/getUsername.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
|
|
||||||
|
export async function getUsername(name) {
|
||||||
|
let available = await fetchWithTimeout('/account/username?name=' + encodeURIComponent(name), { method: 'GET' })
|
||||||
|
checkResponse(available)
|
||||||
|
return await available.json()
|
||||||
|
}
|
||||||
|
|
10
net/web/src/api/setAccountLogin.js
Normal file
10
net/web/src/api/setAccountLogin.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||||
|
var base64 = require('base-64');
|
||||||
|
|
||||||
|
export async function setAccountLogin(token, username, password) {
|
||||||
|
let headers = new Headers()
|
||||||
|
headers.append('Credentials', 'Basic ' + base64.encode(username + ":" + password));
|
||||||
|
let res = await fetchWithTimeout(`/account/login?agent=${token}`, { method: 'PUT', headers })
|
||||||
|
checkResponse(res);
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
import { useEffect, useState, useRef } from 'react';
|
import { useEffect, useState, useRef } from 'react';
|
||||||
import { setAccountSearchable } from 'api/setAccountSearchable';
|
import { setAccountSearchable } from 'api/setAccountSearchable';
|
||||||
import { getAccountStatus } from 'api/getAccountStatus';
|
import { getAccountStatus } from 'api/getAccountStatus';
|
||||||
|
import { setAccountLogin } from 'api/setAccountLogin';
|
||||||
|
|
||||||
export function useAccountContext() {
|
export function useAccountContext() {
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
@ -47,6 +48,9 @@ export function useAccountContext() {
|
|||||||
setSearchable: async (flag) => {
|
setSearchable: async (flag) => {
|
||||||
await setAccountSearchable(access.current, flag);
|
await setAccountSearchable(access.current, flag);
|
||||||
},
|
},
|
||||||
|
setLogin: async (username, password) => {
|
||||||
|
await setAccountLogin(access.current, username, password);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return { state, actions }
|
return { state, actions }
|
||||||
|
Loading…
Reference in New Issue
Block a user