Jhipster:使用户能够创建自动链接到他们帐户的对象

Jhipster: Enabling a user to create objects that are automatically linked to their account

我正在构建一项服务来帮助人们做出正确的决定。 作为其中的一部分,我需要引导用户完成入职流程,他们在该流程中创建描述其情况的实体。

当他们输入数据时,我希望能够 link 这些实体彼此之间,以及 link 用户之间的实体。

为此,我调查了以下答案:

Jhipster extented user entity and account creation

虽然我的方法相似,但这些都没有回答我的问题。

我已经创建了一个用户元数据对象并通过 JDL link将其编辑到 Jhipster 用户实体 - 现在我需要找到一种方法来获取登录用户,以便我可以添加对登录用户到他们创建的实体。

我已经完成了大部分工作,并从 Jhipster 代码本身获得了指导。

我有一个组件中的方法,我有很多问题。

company: Company;
project: Project;
team: Team;

account: Account;
user: User;
userMetadata: UserMetadata;

linkEntities() {

    // Question 1: Is this the right approach?
    // Find the logged in account, the user is linked to this
    this.accountService.identity().then(account => {
        this.account = account;
    });

    // Find the user for that account
    this.userService.find(this.account.login)
            .subscribe(res => this.user = res.body);

    // Find the metadata
    this.userMetadataService.find(this.user.id)
            .subscribe(res => this.userMetadata = res.body);

    // Question 2: These values are undefined
    // Is there something obvious I am missing that might explain why?
    console.log(this.account);
    console.log(this.user);
    console.log(this.userMetadata);

    // The company, project and team entities have been 
    // created and submitted in a previous function, 
    // here I update them with the references to one another
    this.company.employees.push(currentlyLoggedInUserMetadata)
    this.project.participants.push(currentlyLoggedInUserMetadata)
    this.team.members.push(currentlyLoggedInUserMetadata)

    this.company.teamOwners.push(this.team);
    this.company.companyProjects.push(this.project);

    this.project.implementingTeams.push(this.team);
    this.project.parentCompany = this.company;

    this.team.parentCompany = this.company;
    this.team.teamProjects.push(this.project);

    // And then send the updated entities to the api
    this.subscribeToCompanySaveResponse(this.companyService.update(this.company));
    this.subscribeToProjectSaveResponse(this.projectService.update(this.project));
    this.subscribeToTeamSaveResponse(this.teamService.update(this.team));
}

我不明白为什么上面的三个 console.logs 有错误。我刚刚将这三个值设置在 console.logs 之上。我是 RxJS 的新手 - 可观察对象的工作方式是否有可能导致这种情况?

理想情况下,我希望在用户服务中为已登录用户保留一个全局可用的值(帐户服务中有一个帐户的私有实例,但没有用户——我应该只公开该帐户吗?默认情况下它是私有的?)

我不确定获取当前登录用户的一对一 linked 用户 <--> userMetadata 对象的最佳方法或大多数 'jhipster' 方法是什么。

我也很清楚这是一个试图做很多事情的大型方法。一旦我可以确认整个事情都有效,我将重构它以使其更易于管理。

如果有人对这种方法有建议,做过类似的事情或知道为什么帐户和用户变量特别未定义(我 运行 以管理员身份登录时的方法),我将不胜感激洞察力!

在此先感谢您抽出时间提供建议!

JHipster 提供了一个名为 SecurityUtils 的实用程序 class。您可以使用它来访问当前用户的登录名或他们的 JWT 令牌。

SecurityUtils.getCurrentUserLogin();
SecurityUtils.getCurrentUserJWT();

如果出于您的目的需要其他信息,您可以使用 UserRepository 来检索整个用户对象,使用 SecurityUtils class.

检索的用户登录信息
UserRepository.findOneByLogin('usersLogin');

这存在于 API 端,因此无需询问前端的帐户对象以了解您想要实现的目标。

P.s。您无法在上述代码中控制台记录帐户信息的原因是因为检索该信息的承诺尚未解决 - 因此,该对象仍然为空。您必须将 console.log 放入您的承诺决议中,即

this.accountService.identity().then(account => {
    this.account = account;
    console.log(this.account);
});

其他请求需要相同的方法。

非常感谢 Phobos 提供的信息,我创建了一个简单有效的解决方案。

我将在下面为将来可能遇到同样问题的其他人详细说明:

作为我当前的 Jhipster 版本 (5.7.2) - 我使用 SecurityUtils 助手编写了一个简单的 API 端点来获取当前登录的用户(或者更具体地说,他们的元数据 - 这是具有 1-1 映射到 Jhipster 特定用户实体的任意实体)。

我首先向元数据实体存储库添加了一个方法:

/**
 * Spring Data  repository for the UserMetadata entity.
 */
@SuppressWarnings("unused")
@Repository
public interface UserMetadataRepository extends JpaRepository<UserMetadata, Long> {
    Optional<UserMetadata> findOneByUser(User user);
}

我使用单独的服务 classes,所以在用户元数据服务中调用了存储库 class:

    /**
     * Get the user metadata object that is associated with the currently logged in user
     * @return an optional containing nothing, or the metadata object
     */
    public Optional<UserMetadata> getUserMetadataForCurrentUser() {

        Optional<UserMetadata> userMetadata = Optional.empty();

        Optional<User> currentUser = SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneByLogin);

        if (currentUser.isPresent()) {
            userMetadata = userMetadataRepository.findOneByUser(currentUser.get());
        }

        return userMetadata;
    }

请注意,我通过将大部分逻辑放在 API 上使它变得更容易,这样客户端就可以尽可能地愚蠢。我喜欢聪明的 API 和愚蠢的客户。

在上面我使用securityUtils获取用户的登录信息,然后通过登录信息找到该用户的用户元数据。客户端永远不必询问实际的用户对象。

我将 UserMetadata 类型的 Optional 传递给 Web 层,它使用 Jhipster 的 ResponseUtil 来 return 可选中的对象,或者一个错误:

    /**
     * GET  /user-metadata/me : get the user metadata of the current user.
     *
     * @return the ResponseEntity with status 200 (OK) and with body the userMetadata, or with status 404 (Not Found)
     */
    @GetMapping("/user-metadata/me")
    @Timed
    public ResponseEntity<UserMetadata> getUserMetadataForCurrentUser() {
        log.debug("REST request to get UserMetadata for current user");
        Optional<UserMetadata> userMetadata = userMetadataService.getUserMetadataForCurrentUser();
        return ResponseUtil.wrapOrNotFound(userMetadata);
    }

然后我们进入前端。在 userMetadata Angular 服务中:

@Injectable({ providedIn: 'root' })
export class UserMetadataService {
    public resourceUrl = SERVER_API_URL + 'api/user-metadata';

    currentUserMetadata: UserMetadata;

    constructor(protected http: HttpClient) {
        this.getCurrentUserMetadata().subscribe(res => (this.currentUserMetadata = res.body));
    }

    getCurrentUserMetadata() {
        return this.http.get<IUserMetadata>(`${this.resourceUrl}/me`, { observe: 'response' });
    }

// Rest of File

我决定设置一个全局可用的值,这样我的其他组件和服务就可以只获取元数据变量,而不必每次都调用它。 我创建了一个方法来调用新的 API 端点,并在构造函数中使用该方法,以便客户端始终可以使用该对象。

我已经尽力将复杂性从下游消费者那里推开。我最初询问的入职组件现在可以通过三行代码实现目标:

this.company.employees.push(this.userMetadataService.currentUserMetadata);
this.project.participants.push(this.userMetadataService.currentUserMetadata);
this.team.members.push(this.userMetadataService.currentUserMetadata);

其余部分隐藏在服务和 api 本身中。

希望其他人发现此信息有用。 我试图彻底解释,因为当我第一次深入研究代码库时,这非常令人困惑。 Jhipster 为您做了很多很酷的事情,但就我而言,这实际上导致了 'It happens with magic' 与 'I understand the mechanics of how this works'.

的感觉

现在我对这个特定功能的工作原理有了更好的了解!