예제 #1
0
  @Async
  protected void notifyUsers(Topic topic, TopicReply reply, String cnt, int userId) {
    String replyAuthorName = dao.fetch(User.class, userId).getName();
    // 通知原本的作者
    if (topic.getUserId() != userId) {
      String alert = replyAuthorName + "回复了您的帖子";
      pushUser(
          topic.getUserId(),
          alert,
          topic.getId(),
          replyAuthorName,
          topic.getTitle(),
          PushService.PUSH_TYPE_REPLY);
    }

    Set<String> ats = findAt(cnt, 5);
    for (String at : ats) {
      User user = dao.fetch(User.class, at);
      if (user == null) continue;
      if (topic.getUserId() == user.getId()) continue; // 前面已经发过了
      if (userId == user.getId()) continue; // 自己@自己, 忽略
      String alert = replyAuthorName + "在帖子回复中@了你";
      pushUser(
          user.getId(),
          alert,
          topic.getId(),
          replyAuthorName,
          topic.getTitle(),
          PushService.PUSH_TYPE_AT);
    }
  }
예제 #2
0
 @At("/passwd/reset")
 public void resetPassword(String email, HttpServletRequest req) {
   if (Strings.isBlank(email)) return;
   User user = dao.fetch(User.class, Cnd.where("email", "=", email));
   if (user == null) return;
   dao.clear(PasswordReset.class, Cnd.where("uid", "=", user.getId()));
   String token = R.UU64() + R.UU64();
   PasswordReset reset = new PasswordReset();
   reset.setUid(dao.fetch(User.class, Cnd.where("email", "=", email)).getId());
   reset.setToken(token);
   dao.insert(reset);
   String url = req.getRequestURL() + "/callback?token=" + token;
   mailService.add2Queue(email, "推爸 密码重置请求", "Reset URL --> " + url);
 }
예제 #3
0
 @Filters(@By(type = AjaxCheckSession.class, args = "me"))
 @At("/update")
 public Object updateInfo(
     String nickName, String passwd, @Attr("me") User me, HttpSession session) {
   if (!Strings.isBlank(nickName)
       && !nickName.startsWith("_") // 系统默认生成的nickName以_开头
       && me.getNickName().startsWith("_") // 只允许修改一次nickName
       && nickName.trim().length() > 1
       && nickName.trim().length() < 10
       && nickName.indexOf("<") < 0
       && nickName.indexOf(">") < 0
       && nickName.indexOf("@") < 0
       && nickName.indexOf("#") < 0
       && nickName.indexOf(" ") < 0
       && nickName.indexOf("&") < 0) {
     try {
       dao.update(
           User.class, Chain.make("nickName", nickName.trim()), Cnd.where("id", "=", me.getId()));
     } catch (Throwable e) {
       return Ajax.fail().setMsg("Nickname is dup or it is BAD!");
     }
   }
   if (!Strings.isBlank(passwd) && passwd.trim().length() > 5 && passwd.trim().length() < 40) {
     dao.update(
         User.class, Chain.make("passwd", xMD5(passwd.trim())), Cnd.where("id", "=", me.getId()));
   }
   session.setAttribute("me", dao.fetch(User.class, Cnd.where("id", "=", me.getId())));
   return Ajax.ok();
 }
예제 #4
0
 @Aop("redis")
 public boolean updateTags(String topicId, @Param("tags") Set<String> tags) {
   if (Strings.isBlank(topicId) || tags == null) {
     return false;
   }
   Topic topic = dao.fetch(Topic.class, topicId);
   if (topic == null) return false;
   Set<String> oldTags = topic.getTags();
   if (oldTags == null) oldTags = new HashSet<>();
   log.debugf("update from '%s' to '%s'", oldTags, tags);
   topic.setTags(tags);
   dao.update(topic, "tags");
   Set<String> newTags = new HashSet<>(tags);
   newTags.removeAll(oldTags);
   Set<String> removeTags = new HashSet<>(oldTags);
   ;
   removeTags.remove(tags);
   fillTopic(topic, null);
   Date lastReplyTime = topic.getCreateTime();
   if (topic.getLastComment() != null) lastReplyTime = topic.getLastComment().getCreateTime();
   Pipeline pipe = jedis().pipelined();
   for (String tag : removeTags) {
     pipe.zrem(RKEY_TOPIC_TAG + tag.toLowerCase().trim(), topic.getId());
     pipe.zincrby(RKEY_TOPIC_TAG_COUNT, -1, tag.toLowerCase().trim());
   }
   for (String tag : newTags) {
     pipe.zadd(RKEY_TOPIC_TAG + tag.toLowerCase().trim(), lastReplyTime.getTime(), topic.getId());
     pipe.zincrby(RKEY_TOPIC_TAG_COUNT, 1, tag.toLowerCase().trim());
   }
   pipe.sync();
   return true;
 }
예제 #5
0
 @At("/passwd/reset/callback")
 public Object resetPasswdCallback(String token) {
   PasswordReset reset = dao.fetch(PasswordReset.class, Cnd.where("token", "=", token));
   if (reset != null) {
     dao.clear(PasswordReset.class, Cnd.where("token", "=", token));
     if (System.currentTimeMillis() - reset.getCreateTime().getTime() > 30 * 60 * 1000)
       return Ajax.fail().setMsg("token is expise");
     String passwd = R.sg(12).next();
     dao.update(
         User.class, Chain.make("passwd", xMD5(passwd)), Cnd.where("id", "=", reset.getUid()));
     String email = dao.fetch(User.class, Cnd.where("id", "=", reset.getUid())).getEmail();
     mailService.add2Queue(email, "推爸密码重置邮件", "Your password : "******"Reset success!! Check you email!");
   }
   return Ajax.fail().setMsg("Token not found!!");
 }
예제 #6
0
  public List<Topic> getRecentReplyTopics(int userId, Pager pager) {

    Map<Integer, UserProfile> authors = new HashMap<Integer, UserProfile>();
    Cnd cnd = Cnd.where("userId", "=", userId);
    cnd.desc("createTime");

    Sql sql =
        Sqls.queryString("select DISTINCT topicId from t_topic_reply $cnd")
            .setEntity(dao.getEntity(TopicReply.class))
            .setVar("cnd", cnd);
    pager.setRecordCount(
        dao.execute(
                Sqls.fetchInt("select count(DISTINCT topicId) from t_topic_reply $cnd")
                    .setEntity(dao.getEntity(TopicReply.class))
                    .setVar("cnd", cnd))
            .getInt());
    sql.setPager(pager);
    String[] replies_topic_ids = dao.execute(sql).getObject(String[].class);
    List<Topic> recent_replies = new ArrayList<Topic>();
    for (String topic_id : replies_topic_ids) {
      Topic _topic = dao.fetch(Topic.class, topic_id);
      if (_topic == null) continue;
      recent_replies.add(_topic);
    }
    if (!recent_replies.isEmpty()) {
      for (Topic topic : recent_replies) {
        fillTopic(topic, authors);
      }
    }
    return recent_replies;
  }
예제 #7
0
 @At
 @Ok("json")
 @AdaptBy(type = JsonAdaptor.class)
 public Object del(
     @Param("..") Store store, @Attr(scope = Scope.SESSION, value = "account") Account acc) {
   dao.delete(dao.fetch(Store.class, store.getId()));
   return store;
 }
예제 #8
0
 @Aop("redis")
 public CResult add(Topic topic, int userId) {
   if (userId < 1) {
     return _fail("请先登录");
   }
   if (Strings.isBlank(topic.getTitle())
       || topic.getTitle().length() > 1024
       || topic.getTitle().length() < 5) {
     return _fail("标题长度不合法");
   }
   if (Strings.isBlank(topic.getContent())) {
     return _fail("内容不合法");
   }
   if (topic.getTags() != null && topic.getTags().size() > 10) {
     return _fail("最多只能有10个tag");
   }
   if (0 != dao.count(Topic.class, Cnd.where("title", "=", topic.getTitle().trim()))) {
     return _fail("相同标题已经发过了");
   }
   topic.setTitle(Strings.escapeHtml(topic.getTitle().trim()));
   topic.setUserId(userId);
   topic.setTop(false);
   topic.setTags(new HashSet<String>());
   if (topic.getType() == null) topic.setType(TopicType.ask);
   topic.setContent(Toolkit.filteContent(topic.getContent()));
   String oldContent = topic.getContent();
   topic.setContentId(bigContentService.put(topic.getContent()));
   topic.setContent(null);
   dao.insert(topic);
   try {
     topic.setContent(oldContent);
     topicSearchService.add(topic);
   } catch (Exception e) {
   }
   // 如果是ask类型,把帖子加入到 "未回复"列表
   Pipeline pipe = jedis().pipelined();
   if (TopicType.ask.equals(topic.getType())) {
     pipe.zadd(RKEY_TOPIC_NOREPLY, System.currentTimeMillis(), topic.getId());
   }
   pipe.zadd(RKEY_TOPIC_UPDATE + topic.getType(), System.currentTimeMillis(), topic.getId());
   if (topic.getType() != TopicType.shortit)
     pipe.zadd(RKEY_TOPIC_UPDATE_ALL, System.currentTimeMillis(), topic.getId());
   pipe.zincrby(RKEY_USER_SCORE, 100, "" + userId);
   pipe.sync();
   String replyAuthorName = dao.fetch(User.class, userId).getName();
   for (Integer watcherId : globalWatcherIds) {
     if (watcherId != userId)
       pushUser(
           watcherId,
           "新帖:" + topic.getTitle(),
           topic.getId(),
           replyAuthorName,
           topic.getTitle(),
           PushService.PUSH_TYPE_REPLY);
   }
   updateTopicTypeCount();
   return _ok(topic.getId());
 }
예제 #9
0
 @At
 public Object login(String email, String passwd, HttpServletRequest req) {
   if (Strings.isBlank(email) || Strings.isBlank(passwd)) return Ajax.fail();
   User me =
       dao.fetch(User.class, Cnd.where("email", "=", email).and("passwd", "=", xMD5(passwd)));
   if (me == null) return Ajax.fail();
   req.getSession().setAttribute("me", me);
   return Ajax.ok();
 }
예제 #10
0
 protected UserProfile _cacheFetch(Map<Integer, UserProfile> authors, int userId) {
   if (authors == null) return null;
   UserProfile author = authors.get(userId);
   if (author == null) {
     author = dao.fetch(UserProfile.class, userId);
     authors.put(userId, author);
   }
   return author;
 }
예제 #11
0
  @Aop("redis")
  public Object check(String topicId, int replies) {
    Topic topic = dao.fetch(Topic.class, topicId);
    if (topic == null) return "";
    Double reply_count = jedis().zscore(RKEY_REPLY_COUNT, topicId);
    if (reply_count == null) reply_count = Double.valueOf(0);
    if (reply_count.intValue() == replies) {
      return "";
    }
    String replyId = jedis().hget(RKEY_REPLY_LAST, topicId);
    TopicReply reply = dao.fetch(TopicReply.class, replyId);
    dao.fetchLinks(reply, null);

    NutMap re = new NutMap().setv("count", reply_count.intValue());
    re.put("data", reply.getAuthor().getNickname() + " 回复了帖子:" + topic.getTitle());
    re.put("options", new NutMap().setv("tag", topicId));
    return re;
  }
예제 #12
0
  @Override
  public List<Item> listSameItems(long itemId) {
    Item item = dao.fetch(Item.class, itemId);
    if (null == item) {
      throw new AppRuntimeException("木有找到该item");
    }

    return dao.query(
        Item.class,
        Cnd.where("oid", "=", item.getOid()).and("skuMoreId", "=", item.getSkuMoreId()));
  }
예제 #13
0
 public void init() {
   if (topicGlobalWatchers != null) {
     for (String username : Strings.splitIgnoreBlank(topicGlobalWatchers)) {
       User user = dao.fetch(User.class, username);
       if (user == null) {
         log.infof("no such user[name=%s] for topic watch", username);
         continue;
       }
       globalWatcherIds.add(user.getId());
     }
   }
 }
예제 #14
0
  @Override
  public Item findWithOrder(long id) {
    if (id <= 0) {
      throw new IllegalParameterException();
    }

    Item item = dao.fetch(Item.class, id);
    if (null != item) {
      dao.fetchLinks(item, "order");
    }
    return item;
  }
예제 #15
0
 @Aop("redis")
 public List<Topic> fetchTop() {
   List<Topic> list = new ArrayList<>();
   Map<Integer, UserProfile> authors = new HashMap<>();
   for (String id : jedis().zrevrangeByScore(RKEY_TOPIC_TOP, Long.MAX_VALUE, 0)) {
     Topic topic = dao.fetch(Topic.class, id);
     if (topic == null) continue;
     fillTopic(topic, authors);
     list.add(topic);
   }
   return list;
 }
 // @RequiresPermissions("topic:index:rebuild")
 public void rebuild() throws IOException {
   Sql sql = Sqls.queryString("select id from t_topic where tp='ask'");
   dao.execute(sql);
   luceneIndex.writer.deleteAll();
   String[] topicIds = sql.getObject(String[].class);
   for (String topicId : topicIds) {
     Topic topic = dao.fetch(Topic.class, topicId);
     bigContentService.fill(topic);
     _add(topic);
   }
   luceneIndex.writer.commit();
 }
예제 #17
0
  @Aop("redis")
  public CResult addReply(final String topicId, final TopicReply reply, final int userId) {
    if (userId < 1) return _fail("请先登录");
    if (reply == null || reply.getContent() == null || reply.getContent().trim().isEmpty()) {
      return _fail("内容不能为空");
    }
    final String cnt = reply.getContent().trim();
    final Topic topic = dao.fetch(Topic.class, topicId); // TODO 改成只fetch出type属性
    if (topic == null) {
      return _fail("主题不存在");
    }
    if (topic.isLock()) {
      return _fail("该帖子已经锁定,不能回复");
    }
    reply.setTopicId(topicId);
    reply.setUserId(userId);
    reply.setContent(Toolkit.filteContent(reply.getContent()));
    reply.setContentId(bigContentService.put(reply.getContent()));
    reply.setContent(null);
    dao.insert(reply);
    // 更新索引
    topicSearchService.add(topic);
    // 更新topic的时间戳
    Pipeline pipe = jedis().pipelined();
    if (topic.isTop()) {
      pipe.zadd(RKEY_TOPIC_TOP, reply.getCreateTime().getTime(), topicId);
    } else {
      pipe.zadd(RKEY_TOPIC_UPDATE + topic.getType(), reply.getCreateTime().getTime(), topicId);
      pipe.zadd(RKEY_TOPIC_UPDATE_ALL, reply.getCreateTime().getTime(), topicId);
    }
    pipe.zrem(RKEY_TOPIC_NOREPLY, topicId);
    if (topic.getTags() != null) {
      for (String tag : topic.getTags()) {
        pipe.zadd(
            RKEY_TOPIC_TAG + tag.toLowerCase().trim(), reply.getCreateTime().getTime(), topicId);
      }
    }
    pipe.hset(RKEY_REPLY_LAST, topicId, reply.getId());
    pipe.zincrby(RKEY_REPLY_COUNT, 1, topicId);
    pipe.zincrby(RKEY_USER_SCORE, 10, "" + userId);
    pipe.sync();

    notifyUsers(topic, reply, cnt, userId);

    return _ok(reply.getId());
  }
예제 #18
0
 @Aop("redis")
 public void fillTopic(Topic topic, Map<Integer, UserProfile> authors) {
   if (topic.getUserId() == 0) topic.setUserId(1);
   topic.setAuthor(_cacheFetch(authors, topic.getUserId()));
   Double reply_count = jedis().zscore(RKEY_REPLY_COUNT, topic.getId());
   topic.setReplyCount(reply_count == null ? 0 : reply_count.intValue());
   if (topic.getReplyCount() > 0) {
     String replyId = jedis().hget(RKEY_REPLY_LAST, topic.getId());
     TopicReply reply = dao.fetch(TopicReply.class, replyId);
     if (reply != null) {
       if (reply.getUserId() == 0) reply.setUserId(1);
       reply.setAuthor(_cacheFetch(authors, reply.getUserId()));
       topic.setLastComment(reply);
     }
   }
   Double visited = jedis().zscore(RKEY_TOPIC_VISIT, topic.getId());
   topic.setVisitCount((visited == null) ? 0 : visited.intValue());
 }
예제 #19
0
 @Override
 public Item find(long id) {
   return dao.fetch(Item.class, id);
 }
예제 #20
0
  /**
   * 找到一个tag和级联的信息
   *
   * @param id
   * @return
   */
  public Resource get(Integer id) {
    Resource resource = dao.fetch(Resource.class, id);

    resourceRelationFull(resource);
    return resource;
  }
예제 #21
0
  @SuppressWarnings("serial")
  public void init(NutConfig nc) {
    NutShiro.DefaultLoginURL = "/admin/logout";
    // 检查环境
    if (!Charset.defaultCharset().name().equalsIgnoreCase(Encoding.UTF8)) {
      log.warn("This project must run in UTF-8, pls add -Dfile.encoding=UTF-8 to JAVA_OPTS");
    }

    // 获取Ioc容器及Dao对象
    Ioc ioc = nc.getIoc();
    // 加载freemarker自定义标签 自定义宏路径
    ioc.get(Configuration.class)
        .setAutoImports(
            new HashMap<String, String>(2) {
              {
                put("p", "/ftl/pony/index.ftl");
                put("s", "/ftl/spring.ftl");
              }
            });
    ioc.get(FreeMarkerConfigurer.class, "mapTags");
    Dao dao = ioc.get(Dao.class);

    // 为全部标注了@Table的bean建表
    Daos.createTablesInPackage(dao, getClass().getPackage().getName() + ".bean", false);

    // 获取配置对象
    PropertiesProxy conf = ioc.get(PropertiesProxy.class, "conf");

    // 初始化SysLog,触发全局系统日志初始化
    ioc.get(SysLogService.class);

    // 初始化默认根用户
    User admin = dao.fetch(User.class, "admin");
    if (admin == null) {
      UserService us = ioc.get(UserService.class);
      admin = us.add("admin", "123456");
    }
    // 初始化游客用户
    User guest = dao.fetch(User.class, "guest");
    if (guest == null) {
      UserService us = ioc.get(UserService.class);
      guest = us.add("guest", "123456");
      UserProfile profile = dao.fetch(UserProfile.class, guest.getId());
      profile.setNickname("游客");
      dao.update(profile, "nickname");
    }

    // 获取NutQuartzCronJobFactory从而触发计划任务的初始化与启动
    ioc.get(NutQuartzCronJobFactory.class);

    // 权限系统初始化
    AuthorityService as = ioc.get(AuthorityService.class);
    as.initFormPackage("net.wendal.nutzbook");
    as.checkBasicRoles(admin);

    // 检查一下Ehcache CacheManager 是否正常.
    CacheManager cacheManager = ioc.get(CacheManager.class);
    log.debug("Ehcache CacheManager = " + cacheManager);
    // CachedNutDaoExecutor.DEBUG = true;

    // 启用FastClass执行入口方法
    Mvcs.disableFastClassInvoker = false;

    // 设置Markdown缓存
    if (cacheManager.getCache("markdown") == null) cacheManager.addCache("markdown");
    Markdowns.cache = cacheManager.getCache("markdown");
    if (conf.getBoolean("cdn.enable", false) && !Strings.isBlank(conf.get("cdn.urlbase"))) {
      MarkdownFunction.cdnbase = conf.get("cdn.urlbase");
    }
  }
예제 #22
0
 @At("/id/?")
 @Ok("json")
 public Object storeid(int id) {
   return dao.fetch(Store.class, id);
 }