🐛 完善用户权限判断

🐛 完善用户权限判断
This commit is contained in:
ronger 2024-05-16 20:34:34 +08:00 committed by GitHub
commit 92cd83e116
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 85 additions and 75 deletions

View File

@ -1,4 +1,4 @@
version: 18
version: 19
jobs:
- name: maven ci
steps:
@ -38,13 +38,12 @@ jobs:
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
caches:
- key: maven-cache
path: /root/.m2/repository
timeout: 3600
- name: package
jobExecutor: internal
steps:
- !CheckoutStep
name: Checkout Code
@ -81,12 +80,9 @@ jobs:
name: Publish Artifacts
artifacts: '**'
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
jobExecutor: internal
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
caches:
- key: maven-cache
path: /root/.m2/repository
@ -109,8 +105,6 @@ jobs:
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
timeout: 3600
- name: Pull from Github
steps:
@ -129,8 +123,6 @@ jobs:
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
timeout: 3600
- name: Push to GitHub
steps:
@ -151,6 +143,22 @@ jobs:
retryCondition: never
maxRetries: 3
retryDelay: 30
cpuRequirement: 250
memoryRequirement: 256
timeout: 3600
- name: test
jobExecutor: internal
steps:
- !CommandStep
name: test
runInContainer: true
image: '@script:builtin:maven:determine-docker-image@'
interpreter: !DefaultInterpreter
commands:
- export ENCRYPTION_KEY=@secret:encryption_key@
- ''
- env
useTTY: false
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
retryCondition: never
maxRetries: 3
retryDelay: 30
timeout: 3600

View File

@ -96,7 +96,7 @@ forest[ˈfôrəst]n.森林)是一款现代化的知识社区项目,使
欢迎对社区提出功能特性方面的建议,我们一起讨论,如果有可能我们会尽快实现。
在提功能建议前可以先看一下 [计划表](https://rymcu.com/article/29) ,避免重复提议
在提功能建议前可以先看一下 [计划表](https://github.com/orgs/rymcu/projects/3) ,避免重复提议
## 鸣谢
- 感谢以下开发者对 Forest 作出的贡献:

View File

@ -17,6 +17,7 @@ import com.rymcu.forest.lucene.service.UserLuceneService;
import com.rymcu.forest.lucene.util.ArticleIndexUtil;
import com.rymcu.forest.lucene.util.PortfolioIndexUtil;
import com.rymcu.forest.lucene.util.UserIndexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -38,6 +39,7 @@ import java.util.concurrent.Executors;
*/
@RestController
@RequestMapping("/api/v1/lucene")
@Slf4j
public class LuceneSearchController {
@Resource
@ -59,22 +61,22 @@ public class LuceneSearchController {
CompletableFuture<String> future =
CompletableFuture.supplyAsync(
() -> {
System.out.println(">>>>>>>>> 开始创建索引 <<<<<<<<<<<");
log.info(">>>>>>>>> 开始创建索引 <<<<<<<<<<<");
luceneService.writeArticle(luceneService.getAllArticleLucene());
userLuceneService.writeUser(userLuceneService.getAllUserLucene());
portfolioLuceneService.writePortfolio(portfolioLuceneService.getAllPortfolioLucene());
System.out.println(">>>>>>>>> 索引创建完毕 <<<<<<<<<<<");
System.out.println("加载用户配置的自定义扩展词典到主词库表");
log.info(">>>>>>>>> 索引创建完毕 <<<<<<<<<<<");
log.info("加载用户配置的自定义扩展词典到主词库表");
try {
System.out.println(">>>>>>>>> 开始加载用户词典 <<<<<<<<<<<");
log.info(">>>>>>>>> 开始加载用户词典 <<<<<<<<<<<");
dicService.writeUserDic();
} catch (FileNotFoundException e) {
System.out.println("加载用户词典失败,未成功创建用户词典");
log.info("加载用户词典失败,未成功创建用户词典");
}
return ">>>>>>>>> 加载用户词典完毕 <<<<<<<<<<<";
},
executor);
future.thenAccept(System.out::println);
future.thenAccept(log::info);
}
/**

View File

@ -20,6 +20,7 @@
package com.rymcu.forest.lucene.dic;
import com.rymcu.forest.lucene.cfg.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@ -31,6 +32,7 @@ import java.util.List;
/**
* 词典管理类,单例模式
*/
@Slf4j
public class Dictionary {
/**
@ -220,7 +222,7 @@ public class Dictionary {
InputStream is;
for (String extDictName : extDictFiles) {
// 读取扩展词典文件
System.out.println("加载扩展词典:" + extDictName);
log.info("加载扩展词典:" + extDictName);
is = this.getClass().getClassLoader().getResourceAsStream(extDictName);
// 如果找不到扩展的字典则忽略
if (is == null) {
@ -238,7 +240,7 @@ public class Dictionary {
theWord = br.readLine();
if (theWord != null && !"".equals(theWord.trim())) {
// 加载扩展词典数据到主内存词典中
System.out.println(theWord);
log.info(theWord);
_MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
}
} while (theWord != null);
@ -267,7 +269,7 @@ public class Dictionary {
if (extStopWordDictFiles != null) {
InputStream is = null;
for (String extStopWordDictName : extStopWordDictFiles) {
System.out.println("加载扩展停止词典:" + extStopWordDictName);
log.info("加载扩展停止词典:" + extStopWordDictName);
// 读取扩展词典文件
is = this.getClass().getClassLoader().getResourceAsStream(extStopWordDictName);
// 如果找不到扩展的字典则忽略
@ -339,7 +341,7 @@ public class Dictionary {
// 加载扩展词典配置
InputStream is;
// 读取扩展词典文件
System.out.println("更新加载扩展词典:" + PATH_USER_DIC);
log.info("更新加载扩展词典:" + PATH_USER_DIC);
try {
is = new FileInputStream(PATH_USER_DIC);
} catch (FileNotFoundException e) {
@ -353,7 +355,7 @@ public class Dictionary {
theWord = br.readLine();
if (theWord != null && !"".equals(theWord.trim())) {
// 加载扩展词典数据到主内存词典中
System.out.println(theWord);
log.info(theWord);
_MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
}
} while (theWord != null);

View File

@ -1,6 +1,7 @@
package com.rymcu.forest.lucene.lucene;
import com.rymcu.forest.lucene.util.IndexUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.index.IndexWriter;
import java.io.File;
@ -15,6 +16,7 @@ import java.util.concurrent.CountDownLatch;
* @author suwen
* @date 2021/2/2 14:14
*/
@Slf4j
public abstract class BaseIndex<T> implements Runnable {
/**
* 父级索引路径
@ -134,7 +136,7 @@ public abstract class BaseIndex<T> implements Runnable {
public void run() {
try {
countDownLatch1.await();
System.out.println(writer);
log.info(writer.toString());
indexDocs(writer, list);
} catch (Exception e) {
e.printStackTrace();

View File

@ -16,6 +16,7 @@ import com.rymcu.forest.mapper.ArticleMapper;
import com.rymcu.forest.service.UserService;
import com.rymcu.forest.util.Html2TextUtil;
import com.rymcu.forest.util.Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
@ -45,6 +46,7 @@ import java.util.concurrent.Executors;
* @author suwen
* @date 2021/2/3 10:29
*/
@Slf4j
@Service
public class LuceneServiceImpl implements LuceneService {
@ -82,11 +84,11 @@ public class LuceneServiceImpl implements LuceneService {
pool.execute(runnable);
}
countDownLatch1.countDown();
System.out.println("开始创建索引");
log.info("开始创建索引");
// 等待所有线程都完成
countDownLatch2.await();
// 线程全部完成工作
System.out.println("所有线程都创建索引完毕");
log.info("所有线程都创建索引完毕");
// 释放线程池资源
pool.shutdown();
} catch (Exception e) {

View File

@ -9,6 +9,7 @@ import com.rymcu.forest.lucene.service.PortfolioLuceneService;
import com.rymcu.forest.lucene.util.LucenePath;
import com.rymcu.forest.lucene.util.PortfolioIndexUtil;
import com.rymcu.forest.lucene.util.SearchUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
@ -38,6 +39,7 @@ import java.util.concurrent.Executors;
* @author suwen
* @date 2021/3/6 10:29
*/
@Slf4j
@Service
public class PortfolioLuceneServiceImpl implements PortfolioLuceneService {
@ -71,11 +73,11 @@ public class PortfolioLuceneServiceImpl implements PortfolioLuceneService {
pool.execute(runnable);
}
countDownLatch1.countDown();
System.out.println("开始创建索引");
log.info("开始创建索引");
// 等待所有线程都完成
countDownLatch2.await();
// 线程全部完成工作
System.out.println("所有线程都创建索引完毕");
log.info("所有线程都创建索引完毕");
// 释放线程池资源
pool.shutdown();
} catch (Exception e) {
@ -180,7 +182,7 @@ public class PortfolioLuceneServiceImpl implements PortfolioLuceneService {
.build());
}
} catch (IOException | ParseException | InvalidTokenOffsetsException e) {
System.out.println(e.getMessage());
log.info(e.getMessage());
e.printStackTrace();
} finally {
service.shutdownNow();

View File

@ -9,6 +9,7 @@ import com.rymcu.forest.lucene.service.UserLuceneService;
import com.rymcu.forest.lucene.util.LucenePath;
import com.rymcu.forest.lucene.util.SearchUtil;
import com.rymcu.forest.lucene.util.UserIndexUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
@ -38,6 +39,7 @@ import java.util.concurrent.Executors;
* @author suwen
* @date 2021/3/6 10:29
*/
@Slf4j
@Service
public class UserLuceneServiceImpl implements UserLuceneService {
@ -70,11 +72,11 @@ public class UserLuceneServiceImpl implements UserLuceneService {
pool.execute(runnable);
}
countDownLatch1.countDown();
System.out.println("开始创建索引");
log.info("开始创建索引");
// 等待所有线程都完成
countDownLatch2.await();
// 线程全部完成工作
System.out.println("所有线程都创建索引完毕");
log.info("所有线程都创建索引完毕");
// 释放线程池资源
pool.shutdown();
} catch (Exception e) {
@ -169,7 +171,7 @@ public class UserLuceneServiceImpl implements UserLuceneService {
.build());
}
} catch (IOException | ParseException | InvalidTokenOffsetsException e) {
System.out.println(e.getMessage());
log.info(e.getMessage());
e.printStackTrace();
} finally {
service.shutdownNow();

View File

@ -3,6 +3,7 @@ package com.rymcu.forest.lucene.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.rymcu.forest.lucene.model.PortfolioLucene;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
@ -18,6 +19,7 @@ import java.util.Arrays;
*
* @author suwen
*/
@Slf4j
public class PortfolioIndexUtil {
/**
@ -50,7 +52,7 @@ public class PortfolioIndexUtil {
* @throws Exception
*/
private static synchronized void creatIndex(PortfolioLucene t) {
System.out.println("创建单个索引");
log.info("创建单个索引");
IndexWriter writer;
try {
boolean create = true;

View File

@ -1,5 +1,6 @@
package com.rymcu.forest.lucene.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
@ -22,6 +23,7 @@ import java.util.concurrent.ExecutorService;
* @author suwen
* @date 2021/2/2 14:04
*/
@Slf4j
public class SearchUtil {
/**
* 获取IndexSearcher对象
@ -129,7 +131,7 @@ public class SearchUtil {
int page, int perPage, IndexSearcher searcher, Query query) throws IOException {
TopDocs result = null;
if (query == null) {
System.out.println(" Query is null return null ");
log.info(" Query is null return null ");
return null;
}
ScoreDoc before = null;

View File

@ -3,6 +3,7 @@ package com.rymcu.forest.lucene.util;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.rymcu.forest.lucene.model.UserLucene;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
@ -20,6 +21,7 @@ import java.util.Arrays;
*
* @author suwen
*/
@Slf4j
public class UserIndexUtil {
/**
@ -57,7 +59,7 @@ public class UserIndexUtil {
* @throws Exception
*/
private static synchronized void creatIndex(UserLucene t) {
System.out.println("创建单个索引");
log.info("创建单个索引");
IndexWriter writer;
try {
boolean create = true;

View File

@ -1,8 +1,6 @@
package com.rymcu.forest.openai;
import com.rymcu.forest.entity.User;
import com.rymcu.forest.openai.service.SseService;
import com.rymcu.forest.util.UserUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

View File

@ -197,4 +197,6 @@ public interface UserService extends Service<User> {
* @return
*/
Set<String> findUserPermissions(User user);
boolean hasAdminPermission(String account);
}

View File

@ -59,7 +59,6 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
private static final int MAX_PREVIEW = 200;
private static final String DEFAULT_STATUS = "0";
private static final String DEFAULT_TOPIC_URI = "news";
private static final int ADMIN_ROLE_WEIGHTS = 2;
@Resource
private ApplicationEventPublisher applicationEventPublisher;
@ -116,8 +115,8 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
String reservedTag = checkTags(articleTags);
boolean notification = false;
if (StringUtils.isNotBlank(reservedTag)) {
Integer roleWeights = userService.findRoleWeightsByUser(user.getIdUser());
if (roleWeights > ADMIN_ROLE_WEIGHTS) {
boolean isAdmin = userService.hasAdminPermission(user.getEmail());
if (!isAdmin) {
throw new UltraViresException(StringEscapeUtils.unescapeJava(reservedTag) + "标签为系统保留标签!");
} else {
notification = true;

View File

@ -162,9 +162,9 @@ public class JavaMailServiceImpl implements JavaMailService {
public void sendTemplateEmail(String deliver, String[] receivers, String[] carbonCopys, String subject, String thymeleafTemplatePath,
Map<String, Object> thymeleafTemplateVariable) throws MessagingException {
String text = null;
if (thymeleafTemplateVariable != null && thymeleafTemplateVariable.size() > 0) {
if (thymeleafTemplateVariable != null && !thymeleafTemplateVariable.isEmpty()) {
Context context = new Context();
thymeleafTemplateVariable.forEach((key, value) -> context.setVariable(key, value));
thymeleafTemplateVariable.forEach(context::setVariable);
text = templateEngine.process(thymeleafTemplatePath, context);
}
sendMimeMail(deliver, receivers, carbonCopys, subject, text, true, null);
@ -181,7 +181,7 @@ public class JavaMailServiceImpl implements JavaMailService {
* src=\"cid:attchmentFileName\"></body></html>
* @param attachmentFilePaths 附件文件路径
* 需要注意的是addInline函数中资源名称attchmentFileName需要与正文中cid:attchmentFileName对应起来
* @throws Exception 邮件发送过程中的异常信息
* @throws MessagingException 邮件发送过程中的异常信息
*/
private void sendMimeMail(String deliver, String[] receivers, String[] carbonCopys, String subject, String text,
boolean isHtml, String[] attachmentFilePaths) throws MessagingException {
@ -196,7 +196,7 @@ public class JavaMailServiceImpl implements JavaMailService {
helper.setSubject(subject);
helper.setText(text, isHtml);
// 添加邮件附件
if (attachmentFilePaths != null && attachmentFilePaths.length > 0) {
if (attachmentFilePaths != null) {
for (String attachmentFilePath : attachmentFilePaths) {
File file = new File(attachmentFilePath);
if (file.exists()) {

View File

@ -332,4 +332,9 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
permissions.add("user");
return permissions;
}
@Override
public boolean hasAdminPermission(String account) {
return userMapper.hasAdminPermission(account);
}
}

View File

@ -9,6 +9,7 @@ import com.rymcu.forest.entity.Follow;
import com.rymcu.forest.entity.Notification;
import com.rymcu.forest.entity.User;
import com.rymcu.forest.service.*;
import lombok.extern.slf4j.Slf4j;
import javax.mail.MessagingException;
import java.util.List;
@ -19,6 +20,7 @@ import java.util.Objects;
*
* @author ronger
*/
@Slf4j
public class NotificationUtils {
private static final NotificationService notificationService = SpringContextHolder.getBean(NotificationService.class);
@ -42,7 +44,7 @@ public class NotificationUtils {
public static void saveNotification(Long idUser, Long dataId, String dataType, String dataSummary) throws MessagingException {
Notification notification = notificationService.findNotification(idUser, dataId, dataType);
if (notification == null || NotificationConstant.UpdateArticle.equals(dataType) || NotificationConstant.UpdateArticleStatus.equals(dataType)) {
System.out.println("------------------- 开始执行消息通知 ------------------");
log.info("------------------- 开始执行消息通知 ------------------");
Integer result = notificationService.save(idUser, dataId, dataType, dataSummary);
if (result == 0) {
// TODO 记录操作失败数据

View File

@ -2,6 +2,7 @@ package com.rymcu.forest.util;
import com.google.common.net.InetAddresses;
import com.google.common.net.InternetDomainName;
import lombok.extern.slf4j.Slf4j;
import java.net.MalformedURLException;
import java.net.URL;
@ -14,6 +15,7 @@ import java.util.Objects;
* @email ronger-x@outlook.com
* @desc : com.rymcu.forest.util
*/
@Slf4j
public class SSRFUtil {
public static boolean checkUrl(URL url, boolean checkWhiteList) {
// 协议限制
@ -42,7 +44,7 @@ public class SSRFUtil {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://rymcu.com");
boolean b = checkUrl(url, false);
System.out.println(b);
log.info(String.valueOf(b));
}
public static boolean internalIp(String ip) {

View File

@ -6,11 +6,7 @@ import com.rymcu.forest.dto.NotificationDTO;
import com.rymcu.forest.dto.PortfolioDTO;
import com.rymcu.forest.dto.UserDTO;
import com.rymcu.forest.entity.Notification;
import com.rymcu.forest.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import javax.servlet.http.HttpServletRequest;
@ -22,13 +18,14 @@ import java.util.Map;
/**
* @author ronger
*/
@Slf4j
public class Utils {
public static final String HASH_ALGORITHM = "SHA-1";
public static final String UNKOWN = "unknown";
public static final int HASH_INTERATIONS = 1024;
public static final int SALT_SIZE = 8;
private static Environment env = SpringContextHolder.getBean(Environment.class);
private static final Environment env = SpringContextHolder.getBean(Environment.class);
/**
* 生成安全的密码生成随机的16位salt并经过1024次 sha-1 hash
@ -53,27 +50,6 @@ public class Utils {
return enpwd.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword));
}
public static User getCurrentUser() {
return null;
}
public static Session getSession() {
try {
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession(false);
if (session == null) {
session = subject.getSession();
}
if (session != null) {
return session;
}
subject.logout();
} catch (InvalidSessionException e) {
}
return null;
}
public static Integer genCode() {
Integer code = (int) ((Math.random() * 9 + 1) * 100000);
return code;
@ -135,7 +111,7 @@ public class Utils {
public static void main(String[] args) {
String s = entryptPassword("admin");
System.out.println(s);
log.info(s);
}
public static Map getArticlesGlobalResult(PageInfo<ArticleDTO> pageInfo) {