Skip to content

Commit

Permalink
feat: 个人中心-安全设置,支持绑定、解绑三方账号
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles7c committed Oct 19, 2023
1 parent 36d52d3 commit efe4557
Show file tree
Hide file tree
Showing 19 changed files with 520 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.charles7c.cnadmin.common.enums;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
* 第三方账号平台枚举
*
* @author Charles7c
* @since 2023/10/19 21:22
*/
@Getter
@RequiredArgsConstructor
public enum SocialSourceEnum {

/** 码云 */
GITEE("码云"),

/** GitHub */
GITHUB("GitHub"),;

private final String description;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http:https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package top.charles7c.cnadmin.system.model.vo;

import java.io.Serializable;

import lombok.Data;

import io.swagger.v3.oas.annotations.media.Schema;

/**
* 第三方账号绑定信息
*
* @author Charles7c
* @since 2023/10/19 21:29
*/
@Data
@Schema(description = "第三方账号绑定信息")
public class UserSocialBindVO implements Serializable {

private static final long serialVersionUID = 1L;

/**
* 来源
*/
@Schema(description = "来源", example = "GITEE")
private String source;

/**
* 描述
*/
@Schema(description = "描述", example = "码云")
private String description;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

package top.charles7c.cnadmin.system.service;

import java.util.List;

import top.charles7c.cnadmin.system.model.entity.UserSocialDO;

import me.zhyd.oauth.model.AuthUser;

/**
* 用户社会化关联业务接口
*
Expand All @@ -44,4 +48,33 @@ public interface UserSocialService {
* 用户社会化关联信息
*/
void saveOrUpdate(UserSocialDO userSocial);

/**
* 根据用户 ID 查询
*
* @param userId
* 用户 ID
* @return 用户社会化关联信息
*/
List<UserSocialDO> listByUserId(Long userId);

/**
* 绑定
*
* @param authUser
* 社交身份信息
* @param userId
* 用户 ID
*/
void bind(AuthUser authUser, Long userId);

/**
* 根据来源和用户 ID 删除
*
* @param source
* 来源
* @param userId
* 用户 ID
*/
void deleteBySourceAndUserId(String source, Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,25 @@

package top.charles7c.cnadmin.system.service.impl;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.hutool.json.JSONUtil;

import top.charles7c.cnadmin.common.util.validate.CheckUtils;
import top.charles7c.cnadmin.system.mapper.UserSocialMapper;
import top.charles7c.cnadmin.system.model.entity.UserSocialDO;
import top.charles7c.cnadmin.system.service.UserSocialService;

import me.zhyd.oauth.model.AuthUser;

/**
* 用户社会化关联业务实现
*
Expand Down Expand Up @@ -54,4 +64,32 @@ public void saveOrUpdate(UserSocialDO userSocial) {
.update();
}
}

@Override
public List<UserSocialDO> listByUserId(Long userId) {
return baseMapper.lambdaQuery().eq(UserSocialDO::getUserId, userId).list();
}

@Override
public void bind(AuthUser authUser, Long userId) {
String source = authUser.getSource();
String openId = authUser.getUuid();
List<UserSocialDO> userSocialList = this.listByUserId(userId);
Set<String> boundSocialSet = userSocialList.stream().map(UserSocialDO::getSource).collect(Collectors.toSet());
CheckUtils.throwIf(boundSocialSet.contains(source), "您已经绑定过了 [{}] 平台,请先解绑");
UserSocialDO userSocial = this.getBySourceAndOpenId(source, openId);
CheckUtils.throwIfNotNull(userSocial, "[{}] 平台账号 [{}] 已被其他用户绑定", source, authUser.getUsername());
userSocial = new UserSocialDO();
userSocial.setUserId(userId);
userSocial.setSource(source);
userSocial.setOpenId(openId);
userSocial.setMetaJson(JSONUtil.toJsonStr(authUser));
userSocial.setLastLoginTime(LocalDateTime.now());
baseMapper.insert(userSocial);
}

@Override
public void deleteBySourceAndUserId(String source, Long userId) {
baseMapper.lambdaUpdate().eq(UserSocialDO::getSource, source).eq(UserSocialDO::getUserId, userId).remove();
}
}
19 changes: 18 additions & 1 deletion continew-admin-ui/src/api/system/user-center.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axios from 'axios';

const BASE_URL = '/system/user/center';
const BASE_URL = '/system/user';

export interface BasicInfoModel {
username: string;
Expand Down Expand Up @@ -43,3 +43,20 @@ export interface UpdateEmailReq {
export function updateEmail(req: UpdateEmailReq) {
return axios.patch(`${BASE_URL}/email`, req);
}

export interface UserSocialBindRecord {
source: string;
description: string;
}

export function listSocial() {
return axios.get<UserSocialBindRecord[]>(`${BASE_URL}/social`);
}

export function bindSocial(source: string, req: any) {
return axios.post(`${BASE_URL}/social/${source}`, req);
}

export function unbindSocial(source: string) {
return axios.delete(`${BASE_URL}/social/${source}`);
}
2 changes: 1 addition & 1 deletion continew-admin-ui/src/views/login/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<div v-else class="account app" @click="toggleLoginMode">
<icon-user /> {{ $t('login.account.txt') }}
</div>
<a-tooltip content="Gitee" mini>
<a-tooltip content="码云" mini>
<a-link class="app" @click="handleSocialAuth('gitee')">
<svg
class="icon"
Expand Down
1 change: 1 addition & 0 deletions continew-admin-ui/src/views/login/locale/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default {
'login.email': 'Email Login',
'login.other': 'Other Login',
'login.ing': 'Login...',
'bind.ing': 'Bind...',

'login.account.placeholder.username': 'Please enter username',
'login.account.placeholder.password': 'Please enter password',
Expand Down
1 change: 1 addition & 0 deletions continew-admin-ui/src/views/login/locale/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default {
'login.email': '邮箱登录',
'login.other': '其他登录方式',
'login.ing': '登录中...',
'bind.ing': '绑定中...',

'login.account.placeholder.username': '请输入用户名',
'login.account.placeholder.password': '请输入密码',
Expand Down
41 changes: 39 additions & 2 deletions continew-admin-ui/src/views/login/social/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<a-spin :loading="loading" :tip="$t('login.ing')">
<a-spin :loading="loading" :tip="isLogin() ? $t('bind.ing') : $t('login.ing')">
<div></div>
</a-spin>
</template>
Expand All @@ -9,6 +9,8 @@
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/store';
import { useI18n } from 'vue-i18n';
import { isLogin } from '@/utils/auth';
import { bindSocial } from '@/api/system/user-center';
const { proxy } = getCurrentInstance() as any;
const { t } = useI18n();
Expand Down Expand Up @@ -45,7 +47,42 @@
loading.value = false;
});
};
handleSocialLogin();
/**
* 绑定第三方账号
*/
const handleBindSocial = () => {
if (loading.value) return;
loading.value = true;
const { redirect, ...othersQuery } = router.currentRoute.value.query;
bindSocial(source, othersQuery)
.then((res) => {
router.push({
name: 'UserCenter',
query: {
tab: 'security-setting',
},
});
proxy.$message.success(res.msg);
})
.catch(() => {
router.push({
name: 'UserCenter',
query: {
tab: 'security-setting',
},
});
})
.finally(() => {
loading.value = false;
});
};
if (isLogin()) {
handleBindSocial();
} else {
handleSocialLogin();
}
</script>

<script lang="ts">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
<a-list-item>
<UpdateEmail />
</a-list-item>
<a-list-item>
<BindSocial />
</a-list-item>
</a-list>
</template>

<script lang="ts" setup>
import UpdatePwd from './security-settings/update-pwd.vue';
import UpdatePhone from './security-settings/update-phone.vue';
import UpdateEmail from './security-settings/update-email.vue';
import BindSocial from './security-settings/bind-social.vue';
</script>

<style scoped lang="less">
Expand All @@ -25,7 +29,8 @@
margin-bottom: 20px;
}
.arco-list-item-meta-avatar {
margin-bottom: 1px;
width: 70px;
margin-right: 24px;
}
.arco-list-item-meta {
padding: 0;
Expand All @@ -37,10 +42,13 @@
border-bottom: 1px solid var(--color-neutral-3);
.arco-list-item-meta-description {
display: flex;
flex-flow: row;
justify-content: space-between;
.tip {
width: 50%;
color: rgb(var(--gray-6));
margin-right: 24px;
}
.content {
flex: 1 1 0;
}
.operation {
margin-right: 6px;
Expand Down
Loading

0 comments on commit efe4557

Please sign in to comment.