Refactor common/team
This commit is contained in:
parent
ae2ed21f05
commit
25589b870c
@ -1,4 +1,4 @@
|
||||
import { IAPIDef, IUserInTeam, team as Team, user as User } from '@rondo.dev/common'
|
||||
import { IAPIDef, IUserInTeam, ITeamService, TeamServiceMethods, UserServiceMethods, TeamActions, UserActions, IUserService, ITeamUsers, Team } from '@rondo.dev/common'
|
||||
import { HTTPClientMock } from '@rondo.dev/http-client'
|
||||
import { getError } from '@rondo.dev/test-utils'
|
||||
import React from 'react'
|
||||
@ -18,11 +18,11 @@ describe('TeamConnector', () => {
|
||||
}
|
||||
|
||||
const [teamClient, teamClientMock] =
|
||||
createClientMock<Team.ITeamService>(Team.TeamServiceMethods)
|
||||
createClientMock<ITeamService>(TeamServiceMethods)
|
||||
const [userClient, userClientMock] =
|
||||
createClientMock<User.IUserService>(User.UserServiceMethods)
|
||||
let teamActions!: Team.TeamActions
|
||||
let userActions!: User.UserActions
|
||||
createClientMock<IUserService>(UserServiceMethods)
|
||||
let teamActions!: TeamActions
|
||||
let userActions!: UserActions
|
||||
beforeEach(() => {
|
||||
teamClientMock.find.mockResolvedValue(teams)
|
||||
teamClientMock.findUsers.mockResolvedValue(users)
|
||||
@ -48,7 +48,7 @@ describe('TeamConnector', () => {
|
||||
</MemoryRouter>,
|
||||
)
|
||||
|
||||
const teams: Team.Team[] = [{
|
||||
const teams: Team[] = [{
|
||||
id: 100,
|
||||
name: 'my-team',
|
||||
userId: 1,
|
||||
@ -57,7 +57,7 @@ describe('TeamConnector', () => {
|
||||
userTeams: [],
|
||||
}]
|
||||
|
||||
const users: Team.ITeamUsers = {
|
||||
const users: ITeamUsers = {
|
||||
teamId: 123,
|
||||
usersInTeam: [{
|
||||
teamId: 123,
|
||||
@ -84,7 +84,7 @@ describe('TeamConnector', () => {
|
||||
})
|
||||
|
||||
it('creates a new team', async () => {
|
||||
const newTeam: Team.Team = {
|
||||
const newTeam: Team = {
|
||||
id: 101,
|
||||
name: 'new-team',
|
||||
createDate: '',
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { team, user } from '@rondo.dev/common'
|
||||
import { TReduxed } from '@rondo.dev/jsonrpc'
|
||||
import { TeamActions, UserActions } from '@rondo.dev/common'
|
||||
import { bindActionCreators, pack, TStateSelector } from '@rondo.dev/redux'
|
||||
import { TeamManager } from './TeamManager'
|
||||
import { ITeamState } from './TeamReducer'
|
||||
|
||||
export function configure<State>(
|
||||
teamActions: team.TeamActions,
|
||||
userActions: user.UserActions,
|
||||
teamActions: TeamActions,
|
||||
userActions: UserActions,
|
||||
getLocalState: TStateSelector<State, ITeamState>,
|
||||
) {
|
||||
const Component = pack(
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { team as Team } from '@rondo.dev/common'
|
||||
import { Button, Control, Heading, Help, Input } from 'bloomer'
|
||||
import React from 'react'
|
||||
import { FaCheck, FaEdit, FaPlusSquare } from 'react-icons/fa'
|
||||
import { TeamActions, Team } from '@rondo.dev/common'
|
||||
|
||||
export type TTeamEditorProps = {
|
||||
type: 'add'
|
||||
onAddTeam: Team.TeamActions['create']
|
||||
onAddTeam: TeamActions['create']
|
||||
} | {
|
||||
type: 'update'
|
||||
onUpdateTeam: Team.TeamActions['update']
|
||||
team: Team.Team
|
||||
onUpdateTeam: TeamActions['update']
|
||||
team: Team
|
||||
}
|
||||
|
||||
export interface ITeamEditorState {
|
||||
@ -27,7 +27,7 @@ extends React.PureComponent<TTeamEditorProps, ITeamEditorState> {
|
||||
name: props.type === 'update' ? this.getName(props.team) : '',
|
||||
}
|
||||
}
|
||||
getName(team?: Team.Team) {
|
||||
getName(team?: Team) {
|
||||
return team ? team.name : ''
|
||||
}
|
||||
componentWillReceiveProps(nextProps: TTeamEditorProps) {
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import { team as Team, TReadonlyRecord } from '@rondo.dev/common'
|
||||
import { TReadonlyRecord, Team, TeamActions } from '@rondo.dev/common'
|
||||
import { Button, Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import React from 'react'
|
||||
import { FaEdit, FaPlus, FaTimes } from 'react-icons/fa'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
export interface ITeamListProps {
|
||||
ListButtons?: React.ComponentType<{team: Team.Team}>
|
||||
teamsById: TReadonlyRecord<number, Team.Team>
|
||||
ListButtons?: React.ComponentType<{team: Team}>
|
||||
teamsById: TReadonlyRecord<number, Team>
|
||||
teamIds: ReadonlyArray<number>
|
||||
onAddTeam: Team.TeamActions['create']
|
||||
onRemoveTeam: Team.TeamActions['remove']
|
||||
onAddTeam: TeamActions['create']
|
||||
onRemoveTeam: TeamActions['remove']
|
||||
}
|
||||
|
||||
export interface ITeamProps {
|
||||
ListButtons?: React.ComponentType<{team: Team.Team}>
|
||||
team: Team.Team
|
||||
onRemoveTeam: Team.TeamActions['remove']
|
||||
ListButtons?: React.ComponentType<{team: Team}>
|
||||
team: Team
|
||||
onRemoveTeam: TeamActions['remove']
|
||||
}
|
||||
|
||||
export class TeamRow extends React.PureComponent<ITeamProps> {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IUserInTeam, team as Team, TReadonlyRecord, user as User } from '@rondo.dev/common'
|
||||
import { IUserInTeam, TReadonlyRecord, TeamActions, UserActions, Team } from '@rondo.dev/common'
|
||||
import { Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import { History, Location } from 'history'
|
||||
import React from 'react'
|
||||
@ -13,12 +13,12 @@ export interface ITeamManagerProps {
|
||||
location: Location
|
||||
match: Match<any>
|
||||
|
||||
ListButtons?: React.ComponentType<{team: Team.Team}>
|
||||
ListButtons?: React.ComponentType<{team: Team}>
|
||||
|
||||
teamActions: Team.TeamActions
|
||||
findUserByEmail: User.UserActions['findUserByEmail']
|
||||
teamActions: TeamActions
|
||||
findUserByEmail: UserActions['findUserByEmail']
|
||||
|
||||
teamsById: TReadonlyRecord<number, Team.Team>
|
||||
teamsById: TReadonlyRecord<number, Team>
|
||||
teamIds: ReadonlyArray<number>
|
||||
|
||||
userKeysByTeamId: TReadonlyRecord<number, ReadonlyArray<string>>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { indexBy, ITeam, IUserInTeam, team as T, TReadonlyRecord, without } from '@rondo.dev/common'
|
||||
import { indexBy, Team as _Team, IUserInTeam, TReadonlyRecord, without, TeamActions } from '@rondo.dev/common'
|
||||
import { createReducer } from '@rondo.dev/jsonrpc'
|
||||
|
||||
export interface ITeamState {
|
||||
@ -6,7 +6,7 @@ export interface ITeamState {
|
||||
readonly error: string
|
||||
|
||||
readonly teamIds: ReadonlyArray<number>
|
||||
readonly teamsById: TReadonlyRecord<number, ITeam>
|
||||
readonly teamsById: TReadonlyRecord<number, _Team>
|
||||
|
||||
readonly userKeysByTeamId: TReadonlyRecord<number, ReadonlyArray<string>>
|
||||
readonly usersByKey: TReadonlyRecord<string, IUserInTeam>
|
||||
@ -28,7 +28,7 @@ function getUserKey(userInTeam: {userId: number, teamId: number}) {
|
||||
}
|
||||
|
||||
export const Team = createReducer('teamService', defaultState)
|
||||
.withMapping<T.TeamActions>({
|
||||
.withMapping<TeamActions>({
|
||||
create(state, action) {
|
||||
return {
|
||||
teamIds: state.teamIds.indexOf(action.payload.id) >= 0
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IUser, IUserInTeam, team as Team, TReadonlyRecord, user as User } from '@rondo.dev/common'
|
||||
import { IUser, IUserInTeam, TReadonlyRecord, TeamActions, UserActions, Team } from '@rondo.dev/common'
|
||||
import { Button, Control, Heading, Help, Input, Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import React from 'react'
|
||||
import { FaCheck, FaTimes, FaUser } from 'react-icons/fa'
|
||||
@ -7,13 +7,13 @@ const EMPTY_ARRAY: ReadonlyArray<string> = []
|
||||
|
||||
export interface ITeamUsersProps {
|
||||
// fetchMyTeams: () => void,
|
||||
fetchUsersInTeam: Team.TeamActions['findUsers']
|
||||
findUserByEmail: User.UserActions['findUserByEmail']
|
||||
fetchUsersInTeam: TeamActions['findUsers']
|
||||
findUserByEmail: UserActions['findUserByEmail']
|
||||
|
||||
onAddUser: Team.TeamActions['addUser']
|
||||
onRemoveUser: Team.TeamActions['removeUser']
|
||||
onAddUser: TeamActions['addUser']
|
||||
onRemoveUser: TeamActions['removeUser']
|
||||
|
||||
team: Team.Team
|
||||
team: Team
|
||||
userKeysByTeamId: TReadonlyRecord<number, ReadonlyArray<string>>
|
||||
usersByKey: TReadonlyRecord<string, IUserInTeam>
|
||||
}
|
||||
@ -25,8 +25,8 @@ export interface ITeamUserProps {
|
||||
}
|
||||
|
||||
export interface IAddUserProps {
|
||||
onAddUser: Team.TeamActions['addUser']
|
||||
onSearchUser: User.UserActions['findUserByEmail']
|
||||
onAddUser: TeamActions['addUser']
|
||||
onSearchUser: UserActions['findUserByEmail']
|
||||
teamId: number
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../comments-common/tsconfig.esm.json"
|
||||
"path": "../common/tsconfig.esm.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
},
|
||||
"references": [
|
||||
{"path": "../redux"},
|
||||
{"path": "../comments-common"}
|
||||
{"path": "../common"}
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { ICredentials } from './ICredentials'
|
||||
import { INewUser } from './INewUser'
|
||||
import { IUser } from './IUser'
|
||||
import { IUser, INewUser } from './user'
|
||||
import { ICredentials } from './auth'
|
||||
|
||||
export interface IAPIDef {
|
||||
'/auth/register': {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
export interface ITeam {
|
||||
readonly id: number
|
||||
readonly name: string
|
||||
readonly userId: number
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
import {ITeam} from './ITeam'
|
||||
|
||||
export interface IUserTeam {
|
||||
userId: number
|
||||
teamId: number
|
||||
roleId: number
|
||||
team?: ITeam
|
||||
}
|
||||
1
packages/common/src/auth/index.ts
Normal file
1
packages/common/src/auth/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './ICredentials'
|
||||
@ -1,26 +1,17 @@
|
||||
export * from './entities'
|
||||
export * from './IContext'
|
||||
export * from './IAPIDef'
|
||||
export * from './ICredentials'
|
||||
export * from './auth'
|
||||
export * from './ILogger'
|
||||
export * from './INewUser'
|
||||
export * from './IRole'
|
||||
export * from './ITeam'
|
||||
export * from './IUser'
|
||||
export * from './IUser'
|
||||
export * from './IUserInTeam'
|
||||
export * from './IUserTeam'
|
||||
export * from './StringUtils'
|
||||
export * from './filterProps'
|
||||
export * from './indexBy'
|
||||
export * from './types'
|
||||
export * from './without'
|
||||
|
||||
import * as team from './team'
|
||||
export {team}
|
||||
|
||||
import * as user from './user'
|
||||
export {user}
|
||||
export * from './team'
|
||||
export * from './user'
|
||||
|
||||
import * as entities from './entities'
|
||||
export {entities}
|
||||
|
||||
5
packages/common/src/team/ITeamAddUserParams.ts
Normal file
5
packages/common/src/team/ITeamAddUserParams.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface ITeamAddUserParams {
|
||||
teamId: number
|
||||
userId: number
|
||||
roleId: number
|
||||
}
|
||||
3
packages/common/src/team/ITeamCreateParams.ts
Normal file
3
packages/common/src/team/ITeamCreateParams.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface ITeamCreateParams {
|
||||
name: string
|
||||
}
|
||||
3
packages/common/src/team/ITeamRemoveParams.ts
Normal file
3
packages/common/src/team/ITeamRemoveParams.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface ITeamRemoveParams {
|
||||
id: number
|
||||
}
|
||||
@ -1,39 +1,13 @@
|
||||
// import {ITeam} from './ITeam'
|
||||
import { TReduxed } from '@rondo.dev/jsonrpc'
|
||||
import { keys } from 'ts-transformer-keys'
|
||||
import { Team } from './entities'
|
||||
import { Team } from '../entities'
|
||||
import { ITeamAddUserParams } from './ITeamAddUserParams'
|
||||
import { ITeamCreateParams } from './ITeamCreateParams'
|
||||
import { ITeamRemoveParams } from './ITeamRemoveParams'
|
||||
import { ITeamUpdateParams } from './ITeamUpdateParams'
|
||||
import { ITeamUsers } from './ITeamUsers'
|
||||
import { IUserInTeam } from './IUserInTeam'
|
||||
|
||||
export { Team }
|
||||
|
||||
export interface ITeamAddUserParams {
|
||||
teamId: number
|
||||
userId: number
|
||||
roleId: number
|
||||
}
|
||||
|
||||
export interface ITeamCreateParams {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface ITeamRemoveParams {
|
||||
id: number
|
||||
}
|
||||
|
||||
export interface ITeamUpdateParams {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface ITeamUsers {
|
||||
teamId: number
|
||||
usersInTeam: IUserInTeam[]
|
||||
}
|
||||
|
||||
export interface IContext {
|
||||
userId: number
|
||||
}
|
||||
|
||||
export interface ITeamService {
|
||||
create(params: ITeamCreateParams): Promise<Team>
|
||||
|
||||
@ -50,8 +24,6 @@ export interface ITeamService {
|
||||
find(): Promise<Team[]>
|
||||
|
||||
findUsers(teamId: number): Promise<ITeamUsers>
|
||||
|
||||
// TODO add other methods
|
||||
}
|
||||
|
||||
export const TeamServiceMethods = keys<ITeamService>()
|
||||
4
packages/common/src/team/ITeamUpdateParams.ts
Normal file
4
packages/common/src/team/ITeamUpdateParams.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface ITeamUpdateParams {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
6
packages/common/src/team/ITeamUsers.ts
Normal file
6
packages/common/src/team/ITeamUsers.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { IUserInTeam } from './IUserInTeam'
|
||||
|
||||
export interface ITeamUsers {
|
||||
teamId: number
|
||||
usersInTeam: IUserInTeam[]
|
||||
}
|
||||
7
packages/common/src/team/index.ts
Normal file
7
packages/common/src/team/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './ITeamAddUserParams'
|
||||
export * from './ITeamCreateParams'
|
||||
export * from './ITeamRemoveParams'
|
||||
export * from './ITeamService'
|
||||
export * from './ITeamUpdateParams'
|
||||
export * from './ITeamUsers'
|
||||
export * from './IUserInTeam'
|
||||
@ -1,4 +1,4 @@
|
||||
import {ICredentials} from './ICredentials'
|
||||
import {ICredentials} from '../auth/ICredentials'
|
||||
|
||||
export interface INewUser extends ICredentials {
|
||||
firstName: string
|
||||
@ -1,18 +1,7 @@
|
||||
import { TReduxed } from '@rondo.dev/jsonrpc'
|
||||
import { keys } from 'ts-transformer-keys'
|
||||
import { ICredentials } from './ICredentials'
|
||||
import { IUser } from './IUser'
|
||||
|
||||
export interface IChangePasswordParams {
|
||||
oldPassword: string
|
||||
newPassword: string
|
||||
}
|
||||
|
||||
export interface ICreateUserParams extends ICredentials {
|
||||
firstName: string
|
||||
lastName: string
|
||||
}
|
||||
|
||||
export interface IUserService {
|
||||
getProfile(): Promise<IUser>
|
||||
// TODO exposing search by email might be a security concern
|
||||
3
packages/common/src/user/index.ts
Normal file
3
packages/common/src/user/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './INewUser'
|
||||
export * from './IUserService'
|
||||
export * from './IUser'
|
||||
@ -1,4 +1,4 @@
|
||||
import { team as Team } from '@rondo.dev/common'
|
||||
import { TeamServiceMethods, ITeamService } from '@rondo.dev/common'
|
||||
import { test } from '../test'
|
||||
|
||||
describe('team', () => {
|
||||
@ -15,9 +15,9 @@ describe('team', () => {
|
||||
})
|
||||
|
||||
const getClient = () =>
|
||||
test.rpc<Team.ITeamService>(
|
||||
test.rpc<ITeamService>(
|
||||
'/rpc/teamService',
|
||||
Team.TeamServiceMethods,
|
||||
TeamServiceMethods,
|
||||
headers,
|
||||
)
|
||||
|
||||
|
||||
@ -6,19 +6,23 @@ import {IUserPermissions} from '../services/IUserPermissions'
|
||||
import {
|
||||
trim,
|
||||
entities as e,
|
||||
team as t,
|
||||
IUserInTeam,
|
||||
ITeamService,
|
||||
ITeamCreateParams,
|
||||
ITeamRemoveParams,
|
||||
ITeamUpdateParams,
|
||||
ITeamAddUserParams,
|
||||
} from '@rondo.dev/common'
|
||||
import { ensureLoggedIn, IContext, RPC } from './RPC'
|
||||
import { IUserInTeam } from '@rondo.dev/common/lib/team/IUserInTeam'
|
||||
|
||||
@ensureLoggedIn
|
||||
export class TeamService implements RPC<t.ITeamService> {
|
||||
export class TeamService implements RPC<ITeamService> {
|
||||
constructor(
|
||||
protected readonly db: IDatabase,
|
||||
protected readonly permissions: IUserPermissions,
|
||||
) {}
|
||||
|
||||
async create(context: IContext, params: t.ITeamCreateParams) {
|
||||
async create(context: IContext, params: ITeamCreateParams) {
|
||||
const userId = context.user!.id
|
||||
const name = trim(params.name)
|
||||
|
||||
@ -42,7 +46,7 @@ export class TeamService implements RPC<t.ITeamService> {
|
||||
return (await this.findOne(context, team.id))!
|
||||
}
|
||||
|
||||
async remove(context: IContext, {id}: t.ITeamRemoveParams) {
|
||||
async remove(context: IContext, {id}: ITeamRemoveParams) {
|
||||
const userId = context.user!.id
|
||||
|
||||
await this.permissions.belongsToTeam({
|
||||
@ -59,7 +63,7 @@ export class TeamService implements RPC<t.ITeamService> {
|
||||
return {id}
|
||||
}
|
||||
|
||||
async update(context: IContext, {id, name}: t.ITeamUpdateParams) {
|
||||
async update(context: IContext, {id, name}: ITeamUpdateParams) {
|
||||
const userId = context.user!.id
|
||||
|
||||
await this.permissions.belongsToTeam({
|
||||
@ -77,7 +81,7 @@ export class TeamService implements RPC<t.ITeamService> {
|
||||
return (await this.findOne(context, id))!
|
||||
}
|
||||
|
||||
async addUser(context: IContext, params: t.ITeamAddUserParams) {
|
||||
async addUser(context: IContext, params: ITeamAddUserParams) {
|
||||
const {userId, teamId, roleId} = params
|
||||
await this.db.getRepository(UserTeam)
|
||||
.save({userId, teamId, roleId})
|
||||
@ -93,7 +97,7 @@ export class TeamService implements RPC<t.ITeamService> {
|
||||
return this._mapUserInTeam(userTeam!)
|
||||
}
|
||||
|
||||
async removeUser(context: IContext, params: t.ITeamAddUserParams) {
|
||||
async removeUser(context: IContext, params: ITeamAddUserParams) {
|
||||
const {teamId, userId, roleId} = params
|
||||
|
||||
await this.permissions.belongsToTeam({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {test} from '../test'
|
||||
import {user} from '@rondo.dev/common'
|
||||
import { IUserService, UserServiceMethods } from '@rondo.dev/common'
|
||||
|
||||
describe('user', () => {
|
||||
|
||||
@ -12,9 +12,9 @@ describe('user', () => {
|
||||
})
|
||||
|
||||
const createService = () => {
|
||||
return test.rpc<user.IUserService>(
|
||||
return test.rpc<IUserService>(
|
||||
'/rpc/userService',
|
||||
user.UserServiceMethods,
|
||||
UserServiceMethods,
|
||||
headers,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { user as u } from '@rondo.dev/common'
|
||||
import { IUserService } from '@rondo.dev/common'
|
||||
import { compare, hash } from 'bcrypt'
|
||||
import createError from 'http-errors'
|
||||
import { IDatabase } from '../database/IDatabase'
|
||||
@ -10,7 +10,7 @@ const SALT_ROUNDS = 10
|
||||
const MIN_PASSWORD_LENGTH = 10
|
||||
|
||||
@ensureLoggedIn
|
||||
export class UserService implements RPC<u.IUserService> {
|
||||
export class UserService implements RPC<IUserService> {
|
||||
constructor(protected readonly db: IDatabase) {}
|
||||
|
||||
async getProfile(context: IContext) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user