feat: 登录

This commit is contained in:
wxg0103 2024-07-11 19:51:28 +08:00
parent 8994ac4b20
commit f1672cfb66
10 changed files with 315 additions and 167 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.13 on 2024-07-11 19:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0002_user_create_time_user_update_time'),
]
operations = [
migrations.AddField(
model_name='user',
name='source',
field=models.CharField(default='LOCAL', max_length=10, verbose_name='来源'),
),
]

View File

@ -0,0 +1,39 @@
import {Result} from '@/request/Result'
import {get, post, del, put} from '@/request/index'
import type {pageRequest} from '@/api/type/common'
import {type Ref} from 'vue'
const prefix = '/auth'
/**
*
*/
const getAuthSetting: (auth_type: string, loading?: Ref<boolean>) => Promise<Result<any>> = (auth_type, loading) => {
return get(`${prefix}/${auth_type}/info`, undefined, loading)
}
/**
*
*/
const postAuthSetting: (data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
data,
loading
) => {
return post(`${prefix}/connection`, data, undefined, loading)
}
/**
*
*/
const putAuthSetting: (auth_type: string, data: any, loading?: Ref<boolean>) => Promise<Result<any>> = (
auth_type,
data,
loading
) => {
return put(`${prefix}/${auth_type}/info`, data, undefined, loading)
}
export default {
getAuthSetting,
postAuthSetting,
putAuthSetting
}

View File

@ -1,26 +1,31 @@
import { Result } from '@/request/Result'
import { get, post } from '@/request/index'
import {Result} from '@/request/Result'
import {get, post} from '@/request/index'
import type {
LoginRequest,
RegisterRequest,
CheckCodeRequest,
ResetPasswordRequest,
User,
ResetCurrentUserPasswordRequest
LoginRequest,
RegisterRequest,
CheckCodeRequest,
ResetPasswordRequest,
User,
ResetCurrentUserPasswordRequest
} from '@/api/type/user'
import type { Ref } from 'vue'
import type {Ref} from 'vue'
/**
*
* @param auth_type
* @param request
* @param loading
* @returns
*/
const login: (request: LoginRequest, loading?: Ref<boolean>) => Promise<Result<string>> = (
request,
loading
const login: (auth_type: string, request: LoginRequest, loading?: Ref<boolean>) => Promise<Result<string>> = (
auth_type,
request,
loading
) => {
return post('/user/login', request, undefined, loading)
if (auth_type !== '') {
return post(`/${auth_type}/login`, request, undefined, loading)
}
return post('/user/login', request, undefined, loading)
}
/**
*
@ -28,7 +33,7 @@ const login: (request: LoginRequest, loading?: Ref<boolean>) => Promise<Result<s
* @returns
*/
const logout: (loading?: Ref<boolean>) => Promise<Result<boolean>> = (loading) => {
return post('/user/logout', undefined, undefined, loading)
return post('/user/logout', undefined, undefined, loading)
}
/**
@ -38,10 +43,10 @@ const logout: (loading?: Ref<boolean>) => Promise<Result<boolean>> = (loading) =
* @returns
*/
const register: (request: RegisterRequest, loading?: Ref<boolean>) => Promise<Result<string>> = (
request,
loading
request,
loading
) => {
return post('/user/register', request, undefined, loading)
return post('/user/register', request, undefined, loading)
}
/**
@ -51,10 +56,10 @@ const register: (request: RegisterRequest, loading?: Ref<boolean>) => Promise<Re
* @returns
*/
const checkCode: (request: CheckCodeRequest, loading?: Ref<boolean>) => Promise<Result<boolean>> = (
request,
loading
request,
loading
) => {
return post('/user/check_code', request, undefined, loading)
return post('/user/check_code', request, undefined, loading)
}
/**
@ -64,11 +69,11 @@ const checkCode: (request: CheckCodeRequest, loading?: Ref<boolean>) => Promise<
* @returns
*/
const sendEmit: (
email: string,
type: 'register' | 'reset_password',
loading?: Ref<boolean>
email: string,
type: 'register' | 'reset_password',
loading?: Ref<boolean>
) => Promise<Result<boolean>> = (email, type, loading) => {
return post('/user/send_email', { email, type }, undefined, loading)
return post('/user/send_email', {email, type}, undefined, loading)
}
/**
*
@ -76,7 +81,7 @@ const sendEmit: (
* @returns
*/
const sendEmailToCurrent: (loading?: Ref<boolean>) => Promise<Result<boolean>> = (loading) => {
return post('/user/current/send_email', undefined, undefined, loading)
return post('/user/current/send_email', undefined, undefined, loading)
}
/**
*
@ -85,10 +90,10 @@ const sendEmailToCurrent: (loading?: Ref<boolean>) => Promise<Result<boolean>> =
* @returns
*/
const resetCurrentUserPassword: (
request: ResetCurrentUserPasswordRequest,
loading?: Ref<boolean>
request: ResetCurrentUserPasswordRequest,
loading?: Ref<boolean>
) => Promise<Result<boolean>> = (request, loading) => {
return post('/user/current/reset_password', request, undefined, loading)
return post('/user/current/reset_password', request, undefined, loading)
}
/**
*
@ -96,7 +101,7 @@ const resetCurrentUserPassword: (
* @returns
*/
const profile: (loading?: Ref<boolean>) => Promise<Result<User>> = (loading) => {
return get('/user', undefined, loading)
return get('/user', undefined, loading)
}
/**
@ -106,10 +111,10 @@ const profile: (loading?: Ref<boolean>) => Promise<Result<User>> = (loading) =>
* @returns
*/
const resetPassword: (
request: ResetPasswordRequest,
loading?: Ref<boolean>
request: ResetPasswordRequest,
loading?: Ref<boolean>
) => Promise<Result<boolean>> = (request, loading) => {
return post('/user/re_password', request, undefined, loading)
return post('/user/re_password', request, undefined, loading)
}
/**
@ -118,17 +123,17 @@ const resetPassword: (
* email_or_username
*/
const getUserList: (email_or_username: string, loading?: Ref<boolean>) => Promise<Result<any>> = (
email_or_username,
loading
email_or_username,
loading
) => {
return get('/user/list', { email_or_username }, loading)
return get('/user/list', {email_or_username}, loading)
}
/**
* profile
*/
const getProfile: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
return get('/profile', undefined, loading)
return get('/profile', undefined, loading)
}
/**
@ -137,24 +142,31 @@ const getProfile: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) =
* @param valid_count 校验数量: 5 | 50 | 2
*/
const getValid: (
valid_type: string,
valid_count: number,
loading?: Ref<boolean>
valid_type: string,
valid_count: number,
loading?: Ref<boolean>
) => Promise<Result<any>> = (valid_type, valid_count, loading) => {
return get(`/valid/${valid_type}/${valid_count}`, undefined, loading)
return get(`/valid/${valid_type}/${valid_count}`, undefined, loading)
}
/**
*
*/
const getAuthType: (loading?: Ref<boolean>) => Promise<Result<any>> = (loading) => {
return get('auth/types', undefined, loading)
}
export default {
login,
register,
sendEmit,
checkCode,
profile,
resetPassword,
sendEmailToCurrent,
resetCurrentUserPassword,
logout,
getUserList,
getProfile,
getValid
login,
register,
sendEmit,
checkCode,
profile,
resetPassword,
sendEmailToCurrent,
resetCurrentUserPassword,
logout,
getUserList,
getProfile,
getValid,
getAuthType
}

View File

@ -2,11 +2,11 @@
<el-dropdown trigger="click" type="primary">
<div class="flex-center cursor">
<AppAvatar>
<img src="@/assets/user-icon.svg" style="width: 54%" alt="" />
<img src="@/assets/user-icon.svg" style="width: 54%" alt=""/>
</AppAvatar>
<span class="ml-8">{{ user.userInfo?.username }}</span>
<el-icon class="el-icon--right">
<CaretBottom />
<CaretBottom/>
</el-icon>
</div>
@ -23,7 +23,7 @@
<el-dropdown-item class="border-t p-8" @click="openResetPassword">
{{ $t('layout.topbar.avatar.resetPassword') }}
</el-dropdown-item>
<div v-hasPermission="new ComplexPermission(['ADMIN'], ['x-pack'], 'AND')">
<div v-hasPermission="new ComplexPermission([], ['x-pack'], 'OR')">
<el-dropdown-item class="border-t p-8" @click="openAPIKeyDialog">
{{ $t('layout.topbar.avatar.apiKey') }}
</el-dropdown-item>
@ -39,19 +39,20 @@
</el-dropdown>
<ResetPassword ref="resetPasswordRef"></ResetPassword>
<AboutDialog ref="AboutDialogRef"></AboutDialog>
<APIKeyDialog :user-id="user.userInfo?.id" ref="APIKeyDialogRef" />
<UserPwdDialog ref="UserPwdDialogRef" />
<APIKeyDialog :user-id="user.userInfo?.id" ref="APIKeyDialogRef"/>
<UserPwdDialog ref="UserPwdDialogRef"/>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import {ref, onMounted} from 'vue'
import useStore from '@/stores'
import { useRouter } from 'vue-router'
import {useRouter} from 'vue-router'
import ResetPassword from './ResetPassword.vue'
import AboutDialog from './AboutDialog.vue'
import UserPwdDialog from '@/views/user-manage/component/UserPwdDialog.vue'
import APIKeyDialog from './APIKeyDialog.vue'
import { ComplexPermission } from '@/utils/permission/type'
const { user } = useStore()
import {ComplexPermission} from '@/utils/permission/type'
const {user} = useStore()
const router = useRouter()
const UserPwdDialogRef = ref()
@ -62,6 +63,7 @@ const resetPasswordRef = ref<InstanceType<typeof ResetPassword>>()
const openAbout = () => {
AboutDialogRef.value?.open()
}
function openAPIKeyDialog() {
APIKeyDialogRef.value.open()
}
@ -72,7 +74,7 @@ const openResetPassword = () => {
const logout = () => {
user.logout().then(() => {
router.push({ name: 'login' })
router.push({name: 'login'})
})
}
@ -85,9 +87,11 @@ onMounted(() => {
<style lang="scss" scoped>
.avatar-dropdown {
min-width: 210px;
.userInfo {
padding: 12px 11px;
}
:deep(.el-dropdown-menu__item) {
padding: 12px 11px;
}

View File

@ -9,4 +9,28 @@ export default {
views,
components,
en,
login: {
authentication: 'Login Authentication',
ldap: {
title: 'LDAP Settings',
address: 'LDAP Address',
serverPlaceholder: 'Please enter LDAP address',
bindDN: 'Bind DN',
bindDNPlaceholder: 'Please enter Bind DN',
password: 'Password',
passwordPlaceholder: 'Please enter password',
ou: 'User OU',
ouPlaceholder: 'Please enter User OU',
ldap_filter: 'User Filter',
ldap_filterPlaceholder: 'Please enter User Filter',
ldap_mapping: 'LDAP Attribute Mapping',
ldap_mappingPlaceholder: 'Please enter LDAP Attribute Mapping',
test: 'Test Connection',
enableAuthentication: 'Enable LDAP Authentication',
save: 'Save',
testConnectionSuccess: 'Test Connection Success',
testConnectionFailed: 'Test Connection Failed',
saveSuccess: 'Save Success',
}
}
};

View File

@ -9,4 +9,28 @@ export default {
views,
components,
zhCn,
login: {
authentication: '登录认证',
ldap: {
title: 'LDAP设置',
address: 'LDAP地址',
serverPlaceholder: '请输入LDAP地址',
bindDN: '绑定DN',
bindDNPlaceholder: '请输入绑定DN',
password: '密码',
passwordPlaceholder: '请输入密码',
ou: '用户OU',
ouPlaceholder: '请输入用户OU',
ldap_filter: '用户过滤器',
ldap_filterPlaceholder: '请输入用户过滤器',
ldap_mapping: 'LDAP属性映射',
ldap_mappingPlaceholder: '请输入LDAP属性映射',
test: '测试连接',
enableAuthentication: '启用LDAP认证',
save: '保存',
testConnectionSuccess: '测试连接成功',
testConnectionFailed: '测试连接失败',
saveSuccess: '保存成功',
}
}
};

View File

@ -85,8 +85,8 @@ const useUserStore = defineStore({
})
},
async login(username: string, password: string) {
return UserApi.login({ username, password }).then((ok) => {
async login(auth_type: string, username: string, password: string) {
return UserApi.login(auth_type, { username, password }).then((ok) => {
this.token = ok.data
localStorage.setItem('token', ok.data)
return this.profile()
@ -98,6 +98,11 @@ const useUserStore = defineStore({
localStorage.removeItem('token')
return true
})
},
async getAuthType() {
return UserApi.getAuthType().then((ok) => {
return ok.data
})
}
}
})

View File

@ -1,72 +1,75 @@
<template>
<div class="p-24" v-loading="loading">
<!-- <el-form
ref="emailFormRef"
:rules="rules"
:model="form"
label-position="top"
require-asterisk-position="right"
<el-form
ref="authFormRef"
:rules="rules"
:model="form"
label-position="top"
require-asterisk-position="right"
>
<el-form-item label="SMTP 主机" prop="email_host">
<el-input v-model="form.email_host" placeholder="请输入 SMTP 主机" />
<el-form-item :label="$t('login.ldap.address')" prop="config_data.ldap_server">
<el-input v-model="form.config_data.ldap_server" :placeholder="$t('login.ldap.serverPlaceholder')"/>
</el-form-item>
<el-form-item label="SMTP 端口" prop="email_port">
<el-input v-model="form.email_port" placeholder="请输入 SMTP 端口" />
<el-form-item :label="$t('login.ldap.bindDN')" prop="config_data.base_dn">
<el-input v-model="form.config_data.base_dn" :placeholder="$t('login.ldap.bindDNPlaceholder')"/>
</el-form-item>
<el-form-item label="SMTP 账户" prop="email_host_user">
<el-input v-model="form.email_host_user" placeholder="请输入 SMTP 账户" />
<el-form-item :label="$t('login.ldap.password')" prop="config_data.password">
<el-input v-model="form.config_data.password" :placeholder="$t('login.ldap.passwordPlaceholder')"
show-password/>
</el-form-item>
<el-form-item label="发件人邮箱" prop="from_email">
<el-input v-model="form.from_email" placeholder="请输入发件人邮箱" />
<el-form-item :label="$t('login.ldap.ou')" prop="config_data.ou">
<el-input v-model="form.config_data.ou" :placeholder="$t('login.ldap.ouPlaceholder')"/>
</el-form-item>
<el-form-item label="密码" prop="email_host_password">
<el-input v-model="form.email_host_password" placeholder="请输入发件人密码" show-password />
<el-form-item :label="$t('login.ldap.ldap_filter')" prop="config_data.ldap_filter">
<el-input v-model="form.config_data.ldap_filter" :placeholder="$t('login.ldap.ldap_filterPlaceholder')"/>
</el-form-item>
<el-form-item :label="$t('login.ldap.ldap_mapping')" prop="config_data.ldap_mapping">
<el-input v-model="form.config_data.ldap_mapping" :placeholder="$t('login.ldap.ldap_mappingPlaceholder')"/>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.email_use_ssl"
>开启SSL(如果SMTP端口是465通常需要启用SSL)
</el-checkbox>
<el-checkbox v-model="form.is_active">{{ $t('login.ldap.enableAuthentication') }}</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.email_use_tls"
>开启TLS(如果SMTP端口是587通常需要启用TLS)</el-checkbox
>
</el-form-item>
<el-button @click="submit(emailFormRef, 'test')" :disabled="loading"> 测试连接 </el-button>
<el-button @click="submit(authFormRef, 'test')" :disabled="loading"> {{ $t('login.ldap.test') }}</el-button>
</el-form>
<div class="text-right">
<el-button @click="submit(emailFormRef)" type="primary" :disabled="loading"> 保存 </el-button>
</div> -->
<el-button @click="submit(authFormRef)" type="primary" :disabled="loading"> {{ $t('login.ldap.save') }}
</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive, ref, watch, onMounted } from 'vue'
import emailApi from '@/api/email-setting'
import type { FormInstance, FormRules } from 'element-plus'
import { MsgSuccess } from '@/utils/message'
import {reactive, ref, watch, onMounted} from 'vue'
import authApi from '@/api/auth-setting'
import type {FormInstance, FormRules} from 'element-plus'
import {t} from '@/locales'
import {MsgSuccess} from '@/utils/message'
const form = ref<any>({
email_host: '',
email_port: '',
email_host_user: '',
email_host_password: '',
email_use_tls: false,
email_use_ssl: false,
from_email: ''
id: '',
auth_type: 'LDAP',
config_data: {
ldap_server: '',
base_dn: '',
password: '',
ou: '',
ldap_filter: '',
ldap_mapping: '',
},
is_active: true
})
const emailFormRef = ref()
const authFormRef = ref()
const loading = ref(false)
const rules = reactive<FormRules<any>>({
email_host: [{ required: true, message: '请输入 SMTP 主机', trigger: 'blur' }],
email_port: [{ required: true, message: '请输入 SMTP 端口', trigger: 'blur' }],
email_host_user: [{ required: true, message: '请输入 SMTP 账户', trigger: 'blur' }],
email_host_password: [{ required: true, message: '请输入发件人邮箱密码', trigger: 'blur' }],
from_email: [{ required: true, message: '请输入发件人邮箱', trigger: 'blur' }]
'config_data.ldap_server': [{required: true, message: t('login.ldap.serverPlaceholder'), trigger: 'blur'}],
'config_data.base_dn': [{required: true, message: t('login.ldap.bindDNPlaceholder'), trigger: 'blur'}],
'config_data.password': [{required: true, message: t('login.ldap.passwordPlaceholder'), trigger: 'blur'}],
'config_data.ou': [{required: true, message: t('login.ldap.ouPlaceholder'), trigger: 'blur'}],
'config_data.ldap_filter': [{required: true, message: t('login.ldap.ldap_filterPlaceholder'), trigger: 'blur'}],
'config_data.ldap_mapping': [{required: true, message: t('login.ldap.ldap_mappingPlaceholder'), trigger: 'blur'}]
})
const submit = async (formEl: FormInstance | undefined, test?: string) => {
@ -74,12 +77,12 @@ const submit = async (formEl: FormInstance | undefined, test?: string) => {
await formEl.validate((valid, fields) => {
if (valid) {
if (test) {
emailApi.postTestEmail(form.value, loading).then((res) => {
MsgSuccess('测试连接成功')
authApi.postAuthSetting(form.value, loading).then((res) => {
MsgSuccess(t('login.ldap.testConnectionSuccess'))
})
} else {
emailApi.putEmailSetting(form.value, loading).then((res) => {
MsgSuccess('设置成功')
authApi.putAuthSetting(form.value.auth_type, form.value, loading).then((res) => {
MsgSuccess(t('login.ldap.saveSuccess'))
})
}
}
@ -87,9 +90,12 @@ const submit = async (formEl: FormInstance | undefined, test?: string) => {
}
function getDetail() {
emailApi.getEmailSetting(loading).then((res: any) => {
authApi.getAuthSetting(form.value.auth_type, loading).then((res: any) => {
if (res.data && JSON.stringify(res.data) !== '{}') {
form.value = res.data
if (res.data.config_data.ldap_mapping) {
form.value.config_data.ldap_mapping = JSON.stringify(JSON.parse(res.data.config_data.ldap_mapping))
}
}
})
}

View File

@ -1,6 +1,6 @@
<template>
<div class="authentication-setting p-24">
<h4>登录认证</h4>
<h4>{{$t('login.authentication')}}</h4>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<template v-for="(item, index) in tabList" :key="index">
<el-tab-pane :label="item.label" :name="item.name">
@ -17,16 +17,13 @@
</div>
</template>
<script setup lang="ts">
import { reactive, ref, computed, onMounted } from 'vue'
import emailApi from '@/api/email-setting'
import type { FormInstance, FormRules } from 'element-plus'
import { MsgSuccess } from '@/utils/message'
import { ref, computed, onMounted } from 'vue'
import LDAP from './component/LDAP.vue'
import { t } from '@/locales'
const activeName = ref('LDAP')
const tabList = [
{
label: 'LDAP设置',
label: t('login.ldap.title'),
name: 'LDAP',
component: LDAP
}

View File

@ -3,19 +3,19 @@
<LoginContainer subTitle="欢迎使用 MaxKB 智能知识库">
<h2 class="mb-24">{{ loginMode || '普通登录' }}</h2>
<el-form
class="login-form"
:rules="rules"
:model="loginForm"
ref="loginFormRef"
@keyup.enter="login"
class="login-form"
:rules="rules"
:model="loginForm"
ref="loginFormRef"
@keyup.enter="login"
>
<div class="mb-24">
<el-form-item prop="username">
<el-input
size="large"
class="input-item"
v-model="loginForm.username"
placeholder="请输入用户名"
size="large"
class="input-item"
v-model="loginForm.username"
placeholder="请输入用户名"
>
</el-input>
</el-form-item>
@ -23,12 +23,12 @@
<div class="mb-24">
<el-form-item prop="password">
<el-input
type="password"
size="large"
class="input-item"
v-model="loginForm.password"
placeholder="请输入密码"
show-password
type="password"
size="large"
class="input-item"
v-model="loginForm.password"
placeholder="请输入密码"
show-password
>
</el-input>
</el-form-item>
@ -40,47 +40,51 @@
注册
</el-button> -->
<el-button
class="forgot-password"
@click="router.push('/forgot_password')"
link
type="primary"
class="forgot-password"
@click="router.push('/forgot_password')"
link
type="primary"
>
忘记密码?
</el-button>
</div>
<!-- <div class="login-gradient-divider lighter mt-24">
<div class="login-gradient-divider lighter mt-24" v-if="modeList.length > 1">
<span>更多登录方式</span>
</div>
<div class="text-center mt-16">
<el-button
v-if="loginMode !== 'LDAP'"
circle
class="login-button-circle color-secondary"
@click="changeMode('LDAP')"
>LDAP</el-button
>
<el-button
v-if="loginMode !== ''"
circle
class="login-button-circle color-secondary"
style="font-size: 24px"
icon="UserFilled"
@click="changeMode('')"
/>
</div> -->
<template v-for="item in modeList">
<el-button
v-if="item !== ''&&loginMode !== item"
circle
:key="item"
class="login-button-circle color-secondary"
@click="changeMode(item)"
>{{ item }}
</el-button>
<el-button
v-if="item === ''&&loginMode !== ''"
circle
:key="item"
class="login-button-circle color-secondary"
style="font-size: 24px"
icon="UserFilled"
@click="changeMode('')"
/>
</template>
</div>
</LoginContainer>
</login-layout>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { LoginRequest } from '@/api/type/user'
import { useRouter } from 'vue-router'
import type { FormInstance, FormRules } from 'element-plus'
import {onMounted, ref} from 'vue'
import type {LoginRequest} from '@/api/type/user'
import {useRouter} from 'vue-router'
import type {FormInstance, FormRules} from 'element-plus'
import useStore from '@/stores'
const loading = ref<boolean>(false)
const { user } = useStore()
const {user} = useStore()
const router = useRouter()
const loginForm = ref<LoginRequest>({
username: '',
@ -105,6 +109,8 @@ const rules = ref<FormRules<LoginRequest>>({
})
const loginFormRef = ref<FormInstance>()
const modeList = ref<string[]>(['']);
const loginMode = ref('')
function changeMode(val: string) {
@ -120,13 +126,25 @@ const login = () => {
loginFormRef.value?.validate().then(() => {
loading.value = true
user
.login(loginForm.value.username, loginForm.value.password)
.then(() => {
router.push({ name: 'home' })
})
.finally(() => (loading.value = false))
.login(loginMode.value, loginForm.value.username, loginForm.value.password)
.then(() => {
router.push({name: 'home'})
})
.finally(() => (loading.value = false))
})
}
onMounted(() => {
user.asyncGetProfile().then((res) => {
if (user.isXPack) {
loading.value = true
user.getAuthType().then((res) => {
modeList.value = [...modeList.value, ...res];
}).finally(() => (loading.value = false))
}
})
})
</script>
<style lang="scss" scope>
.login-gradient-divider {
@ -154,6 +172,7 @@ const login = () => {
top: 50%;
}
}
.login-button-circle {
padding: 25px !important;
}