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()
|
||||
defer garbageSync.Unlock()
|
||||
|
||||
PrintMsg("SAVE NEW ASSET");
|
||||
|
||||
// save new file
|
||||
id := uuid.New().String()
|
||||
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,
|
||||
},
|
||||
|
||||
Route{
|
||||
"SetAccountLogin",
|
||||
strings.ToUpper("Put"),
|
||||
"/account/login",
|
||||
SetAccountLogin,
|
||||
},
|
||||
|
||||
Route{
|
||||
"SetAccountSerchable",
|
||||
strings.ToUpper("Put"),
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { Avatar, Image } from 'antd';
|
||||
import React from 'react'
|
||||
import { Avatar, Space, Image, Modal, Form, Input } from 'antd';
|
||||
import React, { useState } from 'react'
|
||||
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 { Menu, Dropdown } from 'antd';
|
||||
import { Logo } from '../../../Logo/Logo';
|
||||
|
||||
export function Identity() {
|
||||
|
||||
const [ showLogin, setShowLogin ] = useState(false);
|
||||
const { state, actions } = useIdentity()
|
||||
|
||||
const menu = (
|
||||
@ -16,7 +17,7 @@ export function Identity() {
|
||||
<div onClick={() => actions.editProfile()}>Edit Profile</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="1">
|
||||
<div>Change Login</div>
|
||||
<div onClick={() => setShowLogin(true)}>Change Login</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="2">
|
||||
<div onClick={() => actions.logout()}>Sign Out</div>
|
||||
@ -24,6 +25,11 @@ export function Identity() {
|
||||
</MenuWrapper>
|
||||
);
|
||||
|
||||
const onChangeLogin = () => {
|
||||
let saved = actions.setLogin();
|
||||
setShowLogin(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<IdentityWrapper>
|
||||
<IdentityDropdown overlay={menu} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="rightTop">
|
||||
@ -37,7 +43,24 @@ export function Identity() {
|
||||
</div>
|
||||
<RightOutlined />
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useContext, useState, useRef, useEffect } from 'react';
|
||||
import { AppContext } from 'context/AppContext';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { AccountContext } from 'context/AccountContext';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getUsername } from 'api/getUsername';
|
||||
|
||||
export function useIdentity() {
|
||||
|
||||
@ -11,11 +13,21 @@ export function useIdentity() {
|
||||
domain: '',
|
||||
imageUrl: null,
|
||||
image: null,
|
||||
|
||||
username: null,
|
||||
usernameStatus: null,
|
||||
password: null,
|
||||
passwordStatus: null,
|
||||
confirm: null,
|
||||
confirmStatus: null,
|
||||
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
const profile = useContext(ProfileContext);
|
||||
const account = useContext(AccountContext);
|
||||
const app = useContext(AppContext);
|
||||
const debounce = useRef(null);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
@ -31,7 +43,56 @@ export function useIdentity() {
|
||||
},
|
||||
editProfile: () => {
|
||||
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(() => {
|
||||
@ -47,6 +108,7 @@ export function useIdentity() {
|
||||
updateState({ image: identity.image });
|
||||
updateState({ name: identity.name });
|
||||
updateState({ handle: identity.handle });
|
||||
updateState({ username: identity.handle });
|
||||
updateState({ domain: identity.node });
|
||||
}
|
||||
}, [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 { setAccountSearchable } from 'api/setAccountSearchable';
|
||||
import { getAccountStatus } from 'api/getAccountStatus';
|
||||
import { setAccountLogin } from 'api/setAccountLogin';
|
||||
|
||||
export function useAccountContext() {
|
||||
const [state, setState] = useState({
|
||||
@ -47,6 +48,9 @@ export function useAccountContext() {
|
||||
setSearchable: async (flag) => {
|
||||
await setAccountSearchable(access.current, flag);
|
||||
},
|
||||
setLogin: async (username, password) => {
|
||||
await setAccountLogin(access.current, username, password);
|
||||
},
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
Loading…
Reference in New Issue
Block a user