feat: redesign project invite popup
This commit is contained in:
parent
737d2b640f
commit
262f9cbdda
@ -16,7 +16,7 @@ import {
|
||||
} from 'react-router-dom';
|
||||
import {
|
||||
useUpdateProjectMemberRoleMutation,
|
||||
useInviteProjectMemberMutation,
|
||||
useInviteProjectMembersMutation,
|
||||
useDeleteProjectMemberMutation,
|
||||
useToggleTaskLabelMutation,
|
||||
useUpdateProjectNameMutation,
|
||||
@ -84,9 +84,10 @@ type InviteUserData = {
|
||||
suerID?: string;
|
||||
};
|
||||
type UserManagementPopupProps = {
|
||||
projectID: string;
|
||||
users: Array<User>;
|
||||
projectMembers: Array<TaskUser>;
|
||||
onInviteProjectMember: (data: InviteUserData) => void;
|
||||
onInviteProjectMembers: (data: Array<InviteUserData>) => void;
|
||||
};
|
||||
|
||||
const VisibiltyPrivateIcon = styled(Lock)`
|
||||
@ -131,14 +132,14 @@ type MemberFilterOptions = {
|
||||
organization?: boolean;
|
||||
};
|
||||
|
||||
const fetchMembers = async (client: any, options: MemberFilterOptions, input: string, cb: any) => {
|
||||
const fetchMembers = async (client: any, projectID: string, options: MemberFilterOptions, input: string, cb: any) => {
|
||||
if (input && input.trim().length < 3) {
|
||||
return [];
|
||||
}
|
||||
const res = await client.query({
|
||||
query: gql`
|
||||
query {
|
||||
searchMembers(input: {SearchFilter:"${input}"}) {
|
||||
searchMembers(input: {SearchFilter:"${input}", projectID:"${projectID}"}) {
|
||||
similarity
|
||||
confirmed
|
||||
joined
|
||||
@ -165,7 +166,7 @@ const fetchMembers = async (client: any, options: MemberFilterOptions, input: st
|
||||
emails.push(m.user.email);
|
||||
return {
|
||||
label: m.user.fullName,
|
||||
value: { id: m.id, type: 0, profileIcon: m.user.profileIcon },
|
||||
value: { id: m.user.id, type: 0, profileIcon: m.user.profileIcon },
|
||||
};
|
||||
}),
|
||||
];
|
||||
@ -214,6 +215,7 @@ const OptionContent = styled.div`
|
||||
`;
|
||||
|
||||
const UserOption: React.FC<UserOptionProps> = ({ isDisabled, isFocused, innerProps, label, data }) => {
|
||||
console.log(data);
|
||||
return !isDisabled ? (
|
||||
<OptionWrapper {...innerProps} isFocused={isFocused}>
|
||||
<TaskAssignee
|
||||
@ -280,16 +282,24 @@ const InviteContainer = styled.div`
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const UserManagementPopup: React.FC<UserManagementPopupProps> = ({ users, projectMembers, onInviteProjectMember }) => {
|
||||
const UserManagementPopup: React.FC<UserManagementPopupProps> = ({
|
||||
projectID,
|
||||
users,
|
||||
projectMembers,
|
||||
onInviteProjectMembers,
|
||||
}) => {
|
||||
const client = useApolloClient();
|
||||
const [invitedUsers, setInvitedUsers] = useState<Array<any> | null>(null);
|
||||
return (
|
||||
<Popup tab={0} title="Invite a user">
|
||||
<InviteContainer>
|
||||
<AsyncSelect
|
||||
getOptionValue={option => option.value.id}
|
||||
placeholder="Email address or username"
|
||||
noOptionsMessage={() => null}
|
||||
onChange={(e: any) => setInvitedUsers(e ? e.value : null)}
|
||||
onChange={(e: any) => {
|
||||
setInvitedUsers(e);
|
||||
}}
|
||||
isMulti
|
||||
autoFocus
|
||||
cacheOptions
|
||||
@ -301,13 +311,25 @@ const UserManagementPopup: React.FC<UserManagementPopupProps> = ({ users, projec
|
||||
IndicatorSeparator: null,
|
||||
DropdownIndicator: null,
|
||||
}}
|
||||
loadOptions={(i, cb) => fetchMembers(client, {}, i, cb)}
|
||||
loadOptions={(i, cb) => fetchMembers(client, projectID, {}, i, cb)}
|
||||
/>
|
||||
</InviteContainer>
|
||||
<InviteButton
|
||||
onClick={() => {
|
||||
// FUCK, gotta rewrite invite member to be MULTIPLE. SHIT!
|
||||
// onInviteProjectMember();
|
||||
if (invitedUsers) {
|
||||
onInviteProjectMembers(
|
||||
invitedUsers.map(user => {
|
||||
if (user.value.type === 0) {
|
||||
return {
|
||||
userID: user.value.id,
|
||||
};
|
||||
}
|
||||
return {
|
||||
email: user.value.id,
|
||||
};
|
||||
}),
|
||||
);
|
||||
}
|
||||
}}
|
||||
disabled={invitedUsers === null}
|
||||
hoverVariant="none"
|
||||
@ -398,14 +420,17 @@ const Project = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const [inviteProjectMember] = useInviteProjectMemberMutation({
|
||||
const [inviteProjectMembers] = useInviteProjectMembersMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<FindProjectQuery>(
|
||||
client,
|
||||
FindProjectDocument,
|
||||
cache =>
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.members.push({ ...response.data.inviteProjectMember.member });
|
||||
draftCache.findProject.members = [
|
||||
...cache.findProject.members,
|
||||
...response.data.inviteProjectMembers.members,
|
||||
];
|
||||
}),
|
||||
{ projectID },
|
||||
);
|
||||
@ -472,8 +497,10 @@ const Project = () => {
|
||||
showPopup(
|
||||
$target,
|
||||
<UserManagementPopup
|
||||
onInviteProjectMember={userID => {
|
||||
// /inviteProjectMember({ variables: { userID, projectID } });
|
||||
projectID={projectID}
|
||||
onInviteProjectMembers={members => {
|
||||
inviteProjectMembers({ variables: { projectID, members } });
|
||||
hidePopup();
|
||||
}}
|
||||
users={data.users}
|
||||
projectMembers={data.findProject.members}
|
||||
|
@ -289,7 +289,7 @@ export type Mutation = {
|
||||
deleteTeamMember: DeleteTeamMemberPayload;
|
||||
deleteUserAccount: DeleteUserAccountPayload;
|
||||
duplicateTaskGroup: DuplicateTaskGroupPayload;
|
||||
inviteProjectMember: InviteProjectMemberPayload;
|
||||
inviteProjectMembers: InviteProjectMembersPayload;
|
||||
logoutUser: Scalars['Boolean'];
|
||||
removeTaskLabel: Task;
|
||||
setTaskChecklistItemComplete: TaskChecklistItem;
|
||||
@ -439,8 +439,8 @@ export type MutationDuplicateTaskGroupArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationInviteProjectMemberArgs = {
|
||||
input: InviteProjectMember;
|
||||
export type MutationInviteProjectMembersArgs = {
|
||||
input: InviteProjectMembers;
|
||||
};
|
||||
|
||||
|
||||
@ -694,16 +694,21 @@ export type UpdateProjectLabelColor = {
|
||||
labelColorID: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type InviteProjectMember = {
|
||||
projectID: Scalars['UUID'];
|
||||
export type MemberInvite = {
|
||||
userID?: Maybe<Scalars['UUID']>;
|
||||
email?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type InviteProjectMemberPayload = {
|
||||
__typename?: 'InviteProjectMemberPayload';
|
||||
export type InviteProjectMembers = {
|
||||
projectID: Scalars['UUID'];
|
||||
members: Array<MemberInvite>;
|
||||
};
|
||||
|
||||
export type InviteProjectMembersPayload = {
|
||||
__typename?: 'InviteProjectMembersPayload';
|
||||
ok: Scalars['Boolean'];
|
||||
member: Member;
|
||||
projectID: Scalars['UUID'];
|
||||
members: Array<Member>;
|
||||
};
|
||||
|
||||
export type DeleteProjectMember = {
|
||||
@ -1446,19 +1451,18 @@ export type DeleteProjectMemberMutation = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type InviteProjectMemberMutationVariables = {
|
||||
export type InviteProjectMembersMutationVariables = {
|
||||
projectID: Scalars['UUID'];
|
||||
userID?: Maybe<Scalars['UUID']>;
|
||||
email?: Maybe<Scalars['String']>;
|
||||
members: Array<MemberInvite>;
|
||||
};
|
||||
|
||||
|
||||
export type InviteProjectMemberMutation = (
|
||||
export type InviteProjectMembersMutation = (
|
||||
{ __typename?: 'Mutation' }
|
||||
& { inviteProjectMember: (
|
||||
{ __typename?: 'InviteProjectMemberPayload' }
|
||||
& Pick<InviteProjectMemberPayload, 'ok'>
|
||||
& { member: (
|
||||
& { inviteProjectMembers: (
|
||||
{ __typename?: 'InviteProjectMembersPayload' }
|
||||
& Pick<InviteProjectMembersPayload, 'ok'>
|
||||
& { members: Array<(
|
||||
{ __typename?: 'Member' }
|
||||
& Pick<Member, 'id' | 'fullName' | 'username'>
|
||||
& { profileIcon: (
|
||||
@ -1468,7 +1472,7 @@ export type InviteProjectMemberMutation = (
|
||||
{ __typename?: 'Role' }
|
||||
& Pick<Role, 'code' | 'name'>
|
||||
) }
|
||||
) }
|
||||
)> }
|
||||
) }
|
||||
);
|
||||
|
||||
@ -2978,11 +2982,11 @@ export function useDeleteProjectMemberMutation(baseOptions?: ApolloReactHooks.Mu
|
||||
export type DeleteProjectMemberMutationHookResult = ReturnType<typeof useDeleteProjectMemberMutation>;
|
||||
export type DeleteProjectMemberMutationResult = ApolloReactCommon.MutationResult<DeleteProjectMemberMutation>;
|
||||
export type DeleteProjectMemberMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectMemberMutation, DeleteProjectMemberMutationVariables>;
|
||||
export const InviteProjectMemberDocument = gql`
|
||||
mutation inviteProjectMember($projectID: UUID!, $userID: UUID, $email: String) {
|
||||
inviteProjectMember(input: {projectID: $projectID, userID: $userID, email: $email}) {
|
||||
export const InviteProjectMembersDocument = gql`
|
||||
mutation inviteProjectMembers($projectID: UUID!, $members: [MemberInvite!]!) {
|
||||
inviteProjectMembers(input: {projectID: $projectID, members: $members}) {
|
||||
ok
|
||||
member {
|
||||
members {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
@ -2999,33 +3003,32 @@ export const InviteProjectMemberDocument = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type InviteProjectMemberMutationFn = ApolloReactCommon.MutationFunction<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>;
|
||||
export type InviteProjectMembersMutationFn = ApolloReactCommon.MutationFunction<InviteProjectMembersMutation, InviteProjectMembersMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useInviteProjectMemberMutation__
|
||||
* __useInviteProjectMembersMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useInviteProjectMemberMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useInviteProjectMemberMutation` returns a tuple that includes:
|
||||
* To run a mutation, you first call `useInviteProjectMembersMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useInviteProjectMembersMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [inviteProjectMemberMutation, { data, loading, error }] = useInviteProjectMemberMutation({
|
||||
* const [inviteProjectMembersMutation, { data, loading, error }] = useInviteProjectMembersMutation({
|
||||
* variables: {
|
||||
* projectID: // value for 'projectID'
|
||||
* userID: // value for 'userID'
|
||||
* email: // value for 'email'
|
||||
* members: // value for 'members'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useInviteProjectMemberMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>) {
|
||||
return ApolloReactHooks.useMutation<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>(InviteProjectMemberDocument, baseOptions);
|
||||
export function useInviteProjectMembersMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<InviteProjectMembersMutation, InviteProjectMembersMutationVariables>) {
|
||||
return ApolloReactHooks.useMutation<InviteProjectMembersMutation, InviteProjectMembersMutationVariables>(InviteProjectMembersDocument, baseOptions);
|
||||
}
|
||||
export type InviteProjectMemberMutationHookResult = ReturnType<typeof useInviteProjectMemberMutation>;
|
||||
export type InviteProjectMemberMutationResult = ApolloReactCommon.MutationResult<InviteProjectMemberMutation>;
|
||||
export type InviteProjectMemberMutationOptions = ApolloReactCommon.BaseMutationOptions<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>;
|
||||
export type InviteProjectMembersMutationHookResult = ReturnType<typeof useInviteProjectMembersMutation>;
|
||||
export type InviteProjectMembersMutationResult = ApolloReactCommon.MutationResult<InviteProjectMembersMutation>;
|
||||
export type InviteProjectMembersMutationOptions = ApolloReactCommon.BaseMutationOptions<InviteProjectMembersMutation, InviteProjectMembersMutationVariables>;
|
||||
export const UpdateProjectMemberRoleDocument = gql`
|
||||
mutation updateProjectMemberRole($projectID: UUID!, $userID: UUID!, $roleCode: RoleCode!) {
|
||||
updateProjectMemberRole(input: {projectID: $projectID, userID: $userID, roleCode: $roleCode}) {
|
||||
|
@ -1,25 +0,0 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const INVITE_PROJECT_MEMBER_MUTATION = gql`
|
||||
mutation inviteProjectMember($projectID: UUID!, $userID: UUID, $email: String) {
|
||||
inviteProjectMember(input: { projectID: $projectID, userID: $userID, email: $email }) {
|
||||
ok
|
||||
member {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default INVITE_PROJECT_MEMBER_MUTATION;
|
25
frontend/src/shared/graphql/project/inviteProjectMembers.ts
Normal file
25
frontend/src/shared/graphql/project/inviteProjectMembers.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const INVITE_PROJECT_MEMBERS_MUTATION = gql`
|
||||
mutation inviteProjectMembers($projectID: UUID!, $members: [MemberInvite!]!) {
|
||||
inviteProjectMembers(input: { projectID: $projectID, members: $members }) {
|
||||
ok
|
||||
members {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default INVITE_PROJECT_MEMBERS_MUTATION;
|
@ -78,8 +78,11 @@ func newWebCmd() *cobra.Command {
|
||||
return http.ListenAndServe(viper.GetString("server.hostname"), r)
|
||||
},
|
||||
}
|
||||
|
||||
cc.Flags().Bool("migrate", false, "if true, auto run's schema migrations before starting the web server")
|
||||
|
||||
viper.BindPFlag("migrate", cc.Flags().Lookup("migrate"))
|
||||
|
||||
viper.SetDefault("migrate", false)
|
||||
return cc
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ type Querier interface {
|
||||
GetEntityIDForNotificationID(ctx context.Context, notificationID uuid.UUID) (uuid.UUID, error)
|
||||
GetLabelColorByID(ctx context.Context, labelColorID uuid.UUID) (LabelColor, error)
|
||||
GetLabelColors(ctx context.Context) ([]LabelColor, error)
|
||||
GetMemberData(ctx context.Context) ([]GetMemberDataRow, error)
|
||||
GetMemberData(ctx context.Context, projectID uuid.UUID) ([]UserAccount, error)
|
||||
GetMemberProjectIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
|
||||
GetMemberTeamIDsForUserID(ctx context.Context, userID uuid.UUID) ([]uuid.UUID, error)
|
||||
GetNotificationForNotificationID(ctx context.Context, notificationID uuid.UUID) (GetNotificationForNotificationIDRow, error)
|
||||
|
@ -16,7 +16,9 @@ UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetMemberData :many
|
||||
SELECT username, full_name, email, user_id FROM user_account;
|
||||
SELECT * FROM user_account
|
||||
WHERE username != 'system'
|
||||
AND user_id NOT IN (SELECT user_id FROM project_member WHERE project_id = $1);
|
||||
|
||||
-- name: UpdateUserAccountInfo :one
|
||||
UPDATE user_account SET bio = $2, full_name = $3, initials = $4, email = $5
|
||||
|
@ -102,30 +102,32 @@ func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
}
|
||||
|
||||
const getMemberData = `-- name: GetMemberData :many
|
||||
SELECT username, full_name, email, user_id FROM user_account
|
||||
SELECT user_id, created_at, email, username, password_hash, profile_bg_color, full_name, initials, profile_avatar_url, role_code, bio FROM user_account
|
||||
WHERE username != 'system'
|
||||
AND user_id NOT IN (SELECT user_id FROM project_member WHERE project_id = $1)
|
||||
`
|
||||
|
||||
type GetMemberDataRow struct {
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetMemberData(ctx context.Context) ([]GetMemberDataRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getMemberData)
|
||||
func (q *Queries) GetMemberData(ctx context.Context, projectID uuid.UUID) ([]UserAccount, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getMemberData, projectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetMemberDataRow
|
||||
var items []UserAccount
|
||||
for rows.Next() {
|
||||
var i GetMemberDataRow
|
||||
var i UserAccount
|
||||
if err := rows.Scan(
|
||||
&i.Username,
|
||||
&i.FullName,
|
||||
&i.Email,
|
||||
&i.UserID,
|
||||
&i.CreatedAt,
|
||||
&i.Email,
|
||||
&i.Username,
|
||||
&i.PasswordHash,
|
||||
&i.ProfileBgColor,
|
||||
&i.FullName,
|
||||
&i.Initials,
|
||||
&i.ProfileAvatarUrl,
|
||||
&i.RoleCode,
|
||||
&i.Bio,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -127,9 +127,10 @@ type ComplexityRoot struct {
|
||||
TaskGroup func(childComplexity int) int
|
||||
}
|
||||
|
||||
InviteProjectMemberPayload struct {
|
||||
Member func(childComplexity int) int
|
||||
InviteProjectMembersPayload struct {
|
||||
Members func(childComplexity int) int
|
||||
Ok func(childComplexity int) int
|
||||
ProjectID func(childComplexity int) int
|
||||
}
|
||||
|
||||
LabelColor struct {
|
||||
@ -194,7 +195,7 @@ type ComplexityRoot struct {
|
||||
DeleteTeamMember func(childComplexity int, input DeleteTeamMember) int
|
||||
DeleteUserAccount func(childComplexity int, input DeleteUserAccount) int
|
||||
DuplicateTaskGroup func(childComplexity int, input DuplicateTaskGroup) int
|
||||
InviteProjectMember func(childComplexity int, input InviteProjectMember) int
|
||||
InviteProjectMembers func(childComplexity int, input InviteProjectMembers) int
|
||||
LogoutUser func(childComplexity int, input LogoutUser) int
|
||||
RemoveTaskLabel func(childComplexity int, input *RemoveTaskLabelInput) int
|
||||
SetTaskChecklistItemComplete func(childComplexity int, input SetTaskChecklistItemComplete) int
|
||||
@ -454,7 +455,7 @@ type MutationResolver interface {
|
||||
UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*db.ProjectLabel, error)
|
||||
UpdateProjectLabelName(ctx context.Context, input UpdateProjectLabelName) (*db.ProjectLabel, error)
|
||||
UpdateProjectLabelColor(ctx context.Context, input UpdateProjectLabelColor) (*db.ProjectLabel, error)
|
||||
InviteProjectMember(ctx context.Context, input InviteProjectMember) (*InviteProjectMemberPayload, error)
|
||||
InviteProjectMembers(ctx context.Context, input InviteProjectMembers) (*InviteProjectMembersPayload, error)
|
||||
DeleteProjectMember(ctx context.Context, input DeleteProjectMember) (*DeleteProjectMemberPayload, error)
|
||||
UpdateProjectMemberRole(ctx context.Context, input UpdateProjectMemberRole) (*UpdateProjectMemberRolePayload, error)
|
||||
CreateTask(ctx context.Context, input NewTask) (*db.Task, error)
|
||||
@ -801,19 +802,26 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.DuplicateTaskGroupPayload.TaskGroup(childComplexity), true
|
||||
|
||||
case "InviteProjectMemberPayload.member":
|
||||
if e.complexity.InviteProjectMemberPayload.Member == nil {
|
||||
case "InviteProjectMembersPayload.members":
|
||||
if e.complexity.InviteProjectMembersPayload.Members == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.InviteProjectMemberPayload.Member(childComplexity), true
|
||||
return e.complexity.InviteProjectMembersPayload.Members(childComplexity), true
|
||||
|
||||
case "InviteProjectMemberPayload.ok":
|
||||
if e.complexity.InviteProjectMemberPayload.Ok == nil {
|
||||
case "InviteProjectMembersPayload.ok":
|
||||
if e.complexity.InviteProjectMembersPayload.Ok == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.InviteProjectMemberPayload.Ok(childComplexity), true
|
||||
return e.complexity.InviteProjectMembersPayload.Ok(childComplexity), true
|
||||
|
||||
case "InviteProjectMembersPayload.projectID":
|
||||
if e.complexity.InviteProjectMembersPayload.ProjectID == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.InviteProjectMembersPayload.ProjectID(childComplexity), true
|
||||
|
||||
case "LabelColor.colorHex":
|
||||
if e.complexity.LabelColor.ColorHex == nil {
|
||||
@ -1257,17 +1265,17 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Mutation.DuplicateTaskGroup(childComplexity, args["input"].(DuplicateTaskGroup)), true
|
||||
|
||||
case "Mutation.inviteProjectMember":
|
||||
if e.complexity.Mutation.InviteProjectMember == nil {
|
||||
case "Mutation.inviteProjectMembers":
|
||||
if e.complexity.Mutation.InviteProjectMembers == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_inviteProjectMember_args(context.TODO(), rawArgs)
|
||||
args, err := ec.field_Mutation_inviteProjectMembers_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.InviteProjectMember(childComplexity, args["input"].(InviteProjectMember)), true
|
||||
return e.complexity.Mutation.InviteProjectMembers(childComplexity, args["input"].(InviteProjectMembers)), true
|
||||
|
||||
case "Mutation.logoutUser":
|
||||
if e.complexity.Mutation.LogoutUser == nil {
|
||||
@ -2869,24 +2877,28 @@ input UpdateProjectLabelColor {
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
inviteProjectMembers(input: InviteProjectMembers!):
|
||||
InviteProjectMembersPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
input MemberInvite {
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type InviteProjectMemberPayload {
|
||||
input InviteProjectMembers {
|
||||
projectID: UUID!
|
||||
members: [MemberInvite!]!
|
||||
}
|
||||
|
||||
type InviteProjectMembersPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
@ -3715,12 +3727,12 @@ func (ec *executionContext) field_Mutation_duplicateTaskGroup_args(ctx context.C
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_inviteProjectMember_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
func (ec *executionContext) field_Mutation_inviteProjectMembers_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 InviteProjectMember
|
||||
var arg0 InviteProjectMembers
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
arg0, err = ec.unmarshalNInviteProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMember(ctx, tmp)
|
||||
arg0, err = ec.unmarshalNInviteProjectMembers2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMembers(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -5179,7 +5191,7 @@ func (ec *executionContext) _DuplicateTaskGroupPayload_taskGroup(ctx context.Con
|
||||
return ec.marshalNTaskGroup2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTaskGroup(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload_ok(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _InviteProjectMembersPayload_ok(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMembersPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -5187,7 +5199,7 @@ func (ec *executionContext) _InviteProjectMemberPayload_ok(ctx context.Context,
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "InviteProjectMemberPayload",
|
||||
Object: "InviteProjectMembersPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
@ -5213,7 +5225,7 @@ func (ec *executionContext) _InviteProjectMemberPayload_ok(ctx context.Context,
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload_member(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _InviteProjectMembersPayload_projectID(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMembersPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -5221,7 +5233,7 @@ func (ec *executionContext) _InviteProjectMemberPayload_member(ctx context.Conte
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "InviteProjectMemberPayload",
|
||||
Object: "InviteProjectMembersPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
@ -5230,7 +5242,7 @@ func (ec *executionContext) _InviteProjectMemberPayload_member(ctx context.Conte
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Member, nil
|
||||
return obj.ProjectID, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -5242,9 +5254,43 @@ func (ec *executionContext) _InviteProjectMemberPayload_member(ctx context.Conte
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*Member)
|
||||
res := resTmp.(uuid.UUID)
|
||||
fc.Result = res
|
||||
return ec.marshalNMember2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMember(ctx, field.Selections, res)
|
||||
return ec.marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMembersPayload_members(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMembersPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "InviteProjectMembersPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Members, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]Member)
|
||||
fc.Result = res
|
||||
return ec.marshalNMember2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _LabelColor_id(ctx context.Context, field graphql.CollectedField, obj *db.LabelColor) (ret graphql.Marshaler) {
|
||||
@ -6545,7 +6591,7 @@ func (ec *executionContext) _Mutation_updateProjectLabelColor(ctx context.Contex
|
||||
return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectLabel(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _Mutation_inviteProjectMembers(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -6561,7 +6607,7 @@ func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, f
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Mutation_inviteProjectMember_args(ctx, rawArgs)
|
||||
args, err := ec.field_Mutation_inviteProjectMembers_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
@ -6570,7 +6616,7 @@ func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, f
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
directive0 := func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().InviteProjectMember(rctx, args["input"].(InviteProjectMember))
|
||||
return ec.resolvers.Mutation().InviteProjectMembers(rctx, args["input"].(InviteProjectMembers))
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
roles, err := ec.unmarshalNRoleLevel2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐRoleLevelᚄ(ctx, []interface{}{"ADMIN"})
|
||||
@ -6598,10 +6644,10 @@ func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, f
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(*InviteProjectMemberPayload); ok {
|
||||
if data, ok := tmp.(*InviteProjectMembersPayload); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/jordanknott/taskcafe/internal/graph.InviteProjectMemberPayload`, tmp)
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/jordanknott/taskcafe/internal/graph.InviteProjectMembersPayload`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -6613,9 +6659,9 @@ func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, f
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*InviteProjectMemberPayload)
|
||||
res := resTmp.(*InviteProjectMembersPayload)
|
||||
fc.Result = res
|
||||
return ec.marshalNInviteProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx, field.Selections, res)
|
||||
return ec.marshalNInviteProjectMembersPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMembersPayload(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_deleteProjectMember(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
@ -15403,8 +15449,8 @@ func (ec *executionContext) unmarshalInputFindUser(ctx context.Context, obj inte
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputInviteProjectMember(ctx context.Context, obj interface{}) (InviteProjectMember, error) {
|
||||
var it InviteProjectMember
|
||||
func (ec *executionContext) unmarshalInputInviteProjectMembers(ctx context.Context, obj interface{}) (InviteProjectMembers, error) {
|
||||
var it InviteProjectMembers
|
||||
var asMap = obj.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
@ -15415,15 +15461,9 @@ func (ec *executionContext) unmarshalInputInviteProjectMember(ctx context.Contex
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "userID":
|
||||
case "members":
|
||||
var err error
|
||||
it.UserID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "email":
|
||||
var err error
|
||||
it.Email, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
it.Members, err = ec.unmarshalNMemberInvite2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberInviteᚄ(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@ -15451,6 +15491,30 @@ func (ec *executionContext) unmarshalInputLogoutUser(ctx context.Context, obj in
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputMemberInvite(ctx context.Context, obj interface{}) (MemberInvite, error) {
|
||||
var it MemberInvite
|
||||
var asMap = obj.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
case "userID":
|
||||
var err error
|
||||
it.UserID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "email":
|
||||
var err error
|
||||
it.Email, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputMemberSearchFilter(ctx context.Context, obj interface{}) (MemberSearchFilter, error) {
|
||||
var it MemberSearchFilter
|
||||
var asMap = obj.(map[string]interface{})
|
||||
@ -16797,24 +16861,29 @@ func (ec *executionContext) _DuplicateTaskGroupPayload(ctx context.Context, sel
|
||||
return out
|
||||
}
|
||||
|
||||
var inviteProjectMemberPayloadImplementors = []string{"InviteProjectMemberPayload"}
|
||||
var inviteProjectMembersPayloadImplementors = []string{"InviteProjectMembersPayload"}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, obj *InviteProjectMemberPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, inviteProjectMemberPayloadImplementors)
|
||||
func (ec *executionContext) _InviteProjectMembersPayload(ctx context.Context, sel ast.SelectionSet, obj *InviteProjectMembersPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, inviteProjectMembersPayloadImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("InviteProjectMemberPayload")
|
||||
out.Values[i] = graphql.MarshalString("InviteProjectMembersPayload")
|
||||
case "ok":
|
||||
out.Values[i] = ec._InviteProjectMemberPayload_ok(ctx, field, obj)
|
||||
out.Values[i] = ec._InviteProjectMembersPayload_ok(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "member":
|
||||
out.Values[i] = ec._InviteProjectMemberPayload_member(ctx, field, obj)
|
||||
case "projectID":
|
||||
out.Values[i] = ec._InviteProjectMembersPayload_projectID(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "members":
|
||||
out.Values[i] = ec._InviteProjectMembersPayload_members(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
@ -17108,8 +17177,8 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "inviteProjectMember":
|
||||
out.Values[i] = ec._Mutation_inviteProjectMember(ctx, field)
|
||||
case "inviteProjectMembers":
|
||||
out.Values[i] = ec._Mutation_inviteProjectMembers(ctx, field)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
@ -19692,22 +19761,22 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNInviteProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMember(ctx context.Context, v interface{}) (InviteProjectMember, error) {
|
||||
return ec.unmarshalInputInviteProjectMember(ctx, v)
|
||||
func (ec *executionContext) unmarshalNInviteProjectMembers2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMembers(ctx context.Context, v interface{}) (InviteProjectMembers, error) {
|
||||
return ec.unmarshalInputInviteProjectMembers(ctx, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInviteProjectMemberPayload2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v InviteProjectMemberPayload) graphql.Marshaler {
|
||||
return ec._InviteProjectMemberPayload(ctx, sel, &v)
|
||||
func (ec *executionContext) marshalNInviteProjectMembersPayload2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMembersPayload(ctx context.Context, sel ast.SelectionSet, v InviteProjectMembersPayload) graphql.Marshaler {
|
||||
return ec._InviteProjectMembersPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInviteProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v *InviteProjectMemberPayload) graphql.Marshaler {
|
||||
func (ec *executionContext) marshalNInviteProjectMembersPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMembersPayload(ctx context.Context, sel ast.SelectionSet, v *InviteProjectMembersPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._InviteProjectMemberPayload(ctx, sel, v)
|
||||
return ec._InviteProjectMembersPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNLabelColor2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐLabelColor(ctx context.Context, sel ast.SelectionSet, v db.LabelColor) graphql.Marshaler {
|
||||
@ -19830,6 +19899,30 @@ func (ec *executionContext) marshalNMember2ᚖgithubᚗcomᚋjordanknottᚋtaskc
|
||||
return ec._Member(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNMemberInvite2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberInvite(ctx context.Context, v interface{}) (MemberInvite, error) {
|
||||
return ec.unmarshalInputMemberInvite(ctx, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNMemberInvite2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberInviteᚄ(ctx context.Context, v interface{}) ([]MemberInvite, error) {
|
||||
var vSlice []interface{}
|
||||
if v != nil {
|
||||
if tmp1, ok := v.([]interface{}); ok {
|
||||
vSlice = tmp1
|
||||
} else {
|
||||
vSlice = []interface{}{v}
|
||||
}
|
||||
}
|
||||
var err error
|
||||
res := make([]MemberInvite, len(vSlice))
|
||||
for i := range vSlice {
|
||||
res[i], err = ec.unmarshalNMemberInvite2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberInvite(ctx, vSlice[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNMemberList2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMemberList(ctx context.Context, sel ast.SelectionSet, v MemberList) graphql.Marshaler {
|
||||
return ec._MemberList(ctx, sel, &v)
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/taskcafe/internal/auth"
|
||||
"github.com/jordanknott/taskcafe/internal/db"
|
||||
"github.com/jordanknott/taskcafe/internal/logger"
|
||||
"github.com/jordanknott/taskcafe/internal/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
@ -63,10 +64,10 @@ func NewHandler(repo db.Repository) http.Handler {
|
||||
default:
|
||||
fieldName = "ProjectID"
|
||||
}
|
||||
log.WithFields(log.Fields{"typeArg": typeArg, "fieldName": fieldName}).Info("getting field by name")
|
||||
logger.New(ctx).WithFields(log.Fields{"typeArg": typeArg, "fieldName": fieldName}).Info("getting field by name")
|
||||
subjectField := val.FieldByName(fieldName)
|
||||
if !subjectField.IsValid() {
|
||||
log.Error("subject field name does not exist on input type")
|
||||
logger.New(ctx).Error("subject field name does not exist on input type")
|
||||
return nil, errors.New("subject field name does not exist on input type")
|
||||
}
|
||||
if fieldName == "TeamID" && subjectField.IsNil() {
|
||||
@ -76,13 +77,13 @@ func NewHandler(repo db.Repository) http.Handler {
|
||||
}
|
||||
subjectID, ok = subjectField.Interface().(uuid.UUID)
|
||||
if !ok {
|
||||
log.Error("error while casting subject UUID")
|
||||
logger.New(ctx).Error("error while casting subject UUID")
|
||||
return nil, errors.New("error while casting subject uuid")
|
||||
}
|
||||
|
||||
var err error
|
||||
if level == ActionLevelProject {
|
||||
log.WithFields(log.Fields{"subjectID": subjectID}).Info("fetching subject ID by typeArg")
|
||||
logger.New(ctx).WithFields(log.Fields{"subjectID": subjectID}).Info("fetching subject ID by typeArg")
|
||||
if typeArg == ObjectTypeTask {
|
||||
subjectID, err = repo.GetProjectIDForTask(ctx, subjectID)
|
||||
}
|
||||
@ -96,7 +97,7 @@ func NewHandler(repo db.Repository) http.Handler {
|
||||
subjectID, err = repo.GetProjectIDForTaskChecklistItem(ctx, subjectID)
|
||||
}
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while getting subject ID")
|
||||
logger.New(ctx).WithError(err).Error("error while getting subject ID")
|
||||
return nil, err
|
||||
}
|
||||
projectRoles, err := GetProjectRoles(ctx, repo, subjectID)
|
||||
@ -109,13 +110,13 @@ func NewHandler(repo db.Repository) http.Handler {
|
||||
},
|
||||
}
|
||||
}
|
||||
log.WithError(err).Error("error while getting project roles")
|
||||
logger.New(ctx).WithError(err).Error("error while getting project roles")
|
||||
return nil, err
|
||||
}
|
||||
for _, validRole := range roles {
|
||||
log.WithFields(log.Fields{"validRole": validRole}).Info("checking role")
|
||||
logger.New(ctx).WithFields(log.Fields{"validRole": validRole}).Info("checking role")
|
||||
if CompareRoleLevel(projectRoles.TeamRole, validRole) || CompareRoleLevel(projectRoles.ProjectRole, validRole) {
|
||||
log.WithFields(log.Fields{"teamRole": projectRoles.TeamRole, "projectRole": projectRoles.ProjectRole}).Info("is team or project role")
|
||||
logger.New(ctx).WithFields(log.Fields{"teamRole": projectRoles.TeamRole, "projectRole": projectRoles.ProjectRole}).Info("is team or project role")
|
||||
return next(ctx)
|
||||
}
|
||||
}
|
||||
@ -132,7 +133,7 @@ func NewHandler(repo db.Repository) http.Handler {
|
||||
}
|
||||
role, err := repo.GetTeamRoleForUserID(ctx, db.GetTeamRoleForUserIDParams{UserID: userID, TeamID: subjectID})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while getting team roles for user ID")
|
||||
logger.New(ctx).WithError(err).Error("error while getting team roles for user ID")
|
||||
return nil, err
|
||||
}
|
||||
for _, validRole := range roles {
|
||||
|
@ -177,15 +177,15 @@ type FindUser struct {
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type InviteProjectMember struct {
|
||||
type InviteProjectMembers struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID *uuid.UUID `json:"userID"`
|
||||
Email *string `json:"email"`
|
||||
Members []MemberInvite `json:"members"`
|
||||
}
|
||||
|
||||
type InviteProjectMemberPayload struct {
|
||||
type InviteProjectMembersPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
Members []Member `json:"members"`
|
||||
}
|
||||
|
||||
type LogoutUser struct {
|
||||
@ -208,6 +208,11 @@ type Member struct {
|
||||
Member *MemberList `json:"member"`
|
||||
}
|
||||
|
||||
type MemberInvite struct {
|
||||
UserID *uuid.UUID `json:"userID"`
|
||||
Email *string `json:"email"`
|
||||
}
|
||||
|
||||
type MemberList struct {
|
||||
Teams []db.Team `json:"teams"`
|
||||
Projects []db.Project `json:"projects"`
|
||||
|
@ -338,24 +338,28 @@ input UpdateProjectLabelColor {
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
inviteProjectMembers(input: InviteProjectMembers!):
|
||||
InviteProjectMembersPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
input MemberInvite {
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type InviteProjectMemberPayload {
|
||||
input InviteProjectMembers {
|
||||
projectID: UUID!
|
||||
members: [MemberInvite!]!
|
||||
}
|
||||
|
||||
type InviteProjectMembersPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/taskcafe/internal/auth"
|
||||
"github.com/jordanknott/taskcafe/internal/db"
|
||||
"github.com/jordanknott/taskcafe/internal/logger"
|
||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vektah/gqlparser/v2/gqlerror"
|
||||
@ -29,7 +30,7 @@ func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject)
|
||||
return &db.Project{}, errors.New("user id is missing")
|
||||
}
|
||||
createdAt := time.Now().UTC()
|
||||
log.WithFields(log.Fields{"name": input.Name, "teamID": input.TeamID}).Info("creating new project")
|
||||
logger.New(ctx).WithFields(log.Fields{"name": input.Name, "teamID": input.TeamID}).Info("creating new project")
|
||||
var project db.Project
|
||||
var err error
|
||||
if input.TeamID == nil {
|
||||
@ -38,10 +39,10 @@ func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject)
|
||||
Name: input.Name,
|
||||
})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while creating project")
|
||||
logger.New(ctx).WithError(err).Error("error while creating project")
|
||||
return &db.Project{}, err
|
||||
}
|
||||
log.WithFields(log.Fields{"userID": userID, "projectID": project.ProjectID}).Info("creating personal project link")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("creating personal project link")
|
||||
} else {
|
||||
project, err = r.Repository.CreateTeamProject(ctx, db.CreateTeamProjectParams{
|
||||
CreatedAt: createdAt,
|
||||
@ -49,13 +50,13 @@ func (r *mutationResolver) CreateProject(ctx context.Context, input NewProject)
|
||||
TeamID: *input.TeamID,
|
||||
})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while creating project")
|
||||
logger.New(ctx).WithError(err).Error("error while creating project")
|
||||
return &db.Project{}, err
|
||||
}
|
||||
}
|
||||
_, err = r.Repository.CreateProjectMember(ctx, db.CreateProjectMemberParams{ProjectID: project.ProjectID, UserID: userID, AddedAt: createdAt, RoleCode: "admin"})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while creating initial project member")
|
||||
logger.New(ctx).WithError(err).Error("error while creating initial project member")
|
||||
return &db.Project{}, err
|
||||
}
|
||||
return &project, nil
|
||||
@ -124,31 +125,33 @@ func (r *mutationResolver) UpdateProjectLabelColor(ctx context.Context, input Up
|
||||
return &label, err
|
||||
}
|
||||
|
||||
func (r *mutationResolver) InviteProjectMember(ctx context.Context, input InviteProjectMember) (*InviteProjectMemberPayload, error) {
|
||||
if input.Email != nil && input.UserID != nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, &gqlerror.Error{
|
||||
func (r *mutationResolver) InviteProjectMembers(ctx context.Context, input InviteProjectMembers) (*InviteProjectMembersPayload, error) {
|
||||
members := []Member{}
|
||||
for _, invitedMember := range input.Members {
|
||||
if invitedMember.Email != nil && invitedMember.UserID != nil {
|
||||
return &InviteProjectMembersPayload{Ok: false}, &gqlerror.Error{
|
||||
Message: "Both email and userID can not be used to invite a project member",
|
||||
Extensions: map[string]interface{}{
|
||||
"code": "403",
|
||||
},
|
||||
}
|
||||
} else if input.Email == nil && input.UserID == nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, &gqlerror.Error{
|
||||
} else if invitedMember.Email == nil && invitedMember.UserID == nil {
|
||||
return &InviteProjectMembersPayload{Ok: false}, &gqlerror.Error{
|
||||
Message: "Either email or userID must be set to invite a project member",
|
||||
Extensions: map[string]interface{}{
|
||||
"code": "403",
|
||||
},
|
||||
}
|
||||
}
|
||||
if input.UserID != nil {
|
||||
if invitedMember.UserID != nil {
|
||||
addedAt := time.Now().UTC()
|
||||
_, err := r.Repository.CreateProjectMember(ctx, db.CreateProjectMemberParams{ProjectID: input.ProjectID, UserID: *input.UserID, AddedAt: addedAt, RoleCode: "member"})
|
||||
_, err := r.Repository.CreateProjectMember(ctx, db.CreateProjectMemberParams{ProjectID: input.ProjectID, UserID: *invitedMember.UserID, AddedAt: addedAt, RoleCode: "member"})
|
||||
if err != nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
return &InviteProjectMembersPayload{Ok: false}, err
|
||||
}
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, *input.UserID)
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, *invitedMember.UserID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
return &InviteProjectMembersPayload{Ok: false}, err
|
||||
|
||||
}
|
||||
var url *string
|
||||
@ -157,20 +160,20 @@ func (r *mutationResolver) InviteProjectMember(ctx context.Context, input Invite
|
||||
}
|
||||
profileIcon := &ProfileIcon{url, &user.Initials, &user.ProfileBgColor}
|
||||
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: *input.UserID, ProjectID: input.ProjectID})
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: *invitedMember.UserID, ProjectID: input.ProjectID})
|
||||
if err != nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
return &InviteProjectMembersPayload{Ok: false}, err
|
||||
}
|
||||
return &InviteProjectMemberPayload{Ok: true, Member: &Member{
|
||||
ID: *input.UserID,
|
||||
members = append(members, Member{
|
||||
ID: *invitedMember.UserID,
|
||||
FullName: user.FullName,
|
||||
Username: user.Username,
|
||||
ProfileIcon: profileIcon,
|
||||
Role: &db.Role{Code: role.Code, Name: role.Name},
|
||||
}}, nil
|
||||
})
|
||||
}
|
||||
// invite user
|
||||
return &InviteProjectMemberPayload{Ok: false}, errors.New("not implemented")
|
||||
}
|
||||
return &InviteProjectMembersPayload{Ok: false, ProjectID: input.ProjectID, Members: members}, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteProjectMember(ctx context.Context, input DeleteProjectMember) (*DeleteProjectMemberPayload, error) {
|
||||
@ -202,18 +205,18 @@ func (r *mutationResolver) DeleteProjectMember(ctx context.Context, input Delete
|
||||
func (r *mutationResolver) UpdateProjectMemberRole(ctx context.Context, input UpdateProjectMemberRole) (*UpdateProjectMemberRolePayload, error) {
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, input.UserID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get user account")
|
||||
logger.New(ctx).WithError(err).Error("get user account")
|
||||
return &UpdateProjectMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
_, err = r.Repository.UpdateProjectMemberRole(ctx, db.UpdateProjectMemberRoleParams{ProjectID: input.ProjectID,
|
||||
UserID: input.UserID, RoleCode: input.RoleCode.String()})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("update project member role")
|
||||
logger.New(ctx).WithError(err).Error("update project member role")
|
||||
return &UpdateProjectMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: user.UserID, ProjectID: input.ProjectID})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get role for project member")
|
||||
logger.New(ctx).WithError(err).Error("get role for project member")
|
||||
return &UpdateProjectMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
var url *string
|
||||
@ -232,17 +235,17 @@ func (r *mutationResolver) UpdateProjectMemberRole(ctx context.Context, input Up
|
||||
|
||||
func (r *mutationResolver) CreateTask(ctx context.Context, input NewTask) (*db.Task, error) {
|
||||
createdAt := time.Now().UTC()
|
||||
log.WithFields(log.Fields{"positon": input.Position, "taskGroupID": input.TaskGroupID}).Info("creating task")
|
||||
logger.New(ctx).WithFields(log.Fields{"positon": input.Position, "taskGroupID": input.TaskGroupID}).Info("creating task")
|
||||
task, err := r.Repository.CreateTask(ctx, db.CreateTaskParams{input.TaskGroupID, createdAt, input.Name, input.Position})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("issue while creating task")
|
||||
logger.New(ctx).WithError(err).Error("issue while creating task")
|
||||
return &db.Task{}, err
|
||||
}
|
||||
return &task, nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteTask(ctx context.Context, input DeleteTaskInput) (*DeleteTaskPayload, error) {
|
||||
log.WithFields(log.Fields{
|
||||
logger.New(ctx).WithFields(log.Fields{
|
||||
"taskID": input.TaskID,
|
||||
}).Info("deleting task")
|
||||
err := r.Repository.DeleteTaskByID(ctx, input.TaskID)
|
||||
@ -299,8 +302,8 @@ func (r *mutationResolver) UpdateTaskDueDate(ctx context.Context, input UpdateTa
|
||||
func (r *mutationResolver) AssignTask(ctx context.Context, input *AssignTaskInput) (*db.Task, error) {
|
||||
assignedDate := time.Now().UTC()
|
||||
assignedTask, err := r.Repository.CreateTaskAssigned(ctx, db.CreateTaskAssignedParams{input.TaskID, input.UserID, assignedDate})
|
||||
log.WithFields(log.Fields{
|
||||
"userID": assignedTask.UserID,
|
||||
logger.New(ctx).WithFields(log.Fields{
|
||||
"assignedUserID": assignedTask.UserID,
|
||||
"taskID": assignedTask.TaskID,
|
||||
"assignedTaskID": assignedTask.TaskAssignedID,
|
||||
}).Info("assigned task")
|
||||
@ -610,7 +613,7 @@ func (r *mutationResolver) ToggleTaskLabel(ctx context.Context, input ToggleTask
|
||||
createdAt := time.Now().UTC()
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
log.WithFields(log.Fields{"err": err}).Warning("no rows")
|
||||
logger.New(ctx).WithFields(log.Fields{"err": err}).Warning("no rows")
|
||||
_, err := r.Repository.CreateTaskLabelForTask(ctx, db.CreateTaskLabelForTaskParams{
|
||||
TaskID: input.TaskID,
|
||||
ProjectLabelID: input.ProjectLabelID,
|
||||
@ -643,17 +646,17 @@ func (r *mutationResolver) ToggleTaskLabel(ctx context.Context, input ToggleTask
|
||||
func (r *mutationResolver) DeleteTeam(ctx context.Context, input DeleteTeam) (*DeleteTeamPayload, error) {
|
||||
team, err := r.Repository.GetTeamByID(ctx, input.TeamID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
logger.New(ctx).Error(err)
|
||||
return &DeleteTeamPayload{Ok: false}, err
|
||||
}
|
||||
projects, err := r.Repository.GetAllProjectsForTeam(ctx, input.TeamID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
logger.New(ctx).Error(err)
|
||||
return &DeleteTeamPayload{Ok: false}, err
|
||||
}
|
||||
err = r.Repository.DeleteTeamByID(ctx, input.TeamID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
logger.New(ctx).Error(err)
|
||||
return &DeleteTeamPayload{Ok: false}, err
|
||||
}
|
||||
|
||||
@ -708,18 +711,18 @@ func (r *mutationResolver) CreateTeamMember(ctx context.Context, input CreateTea
|
||||
func (r *mutationResolver) UpdateTeamMemberRole(ctx context.Context, input UpdateTeamMemberRole) (*UpdateTeamMemberRolePayload, error) {
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, input.UserID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get user account")
|
||||
logger.New(ctx).WithError(err).Error("get user account")
|
||||
return &UpdateTeamMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
_, err = r.Repository.UpdateTeamMemberRole(ctx, db.UpdateTeamMemberRoleParams{TeamID: input.TeamID,
|
||||
UserID: input.UserID, RoleCode: input.RoleCode.String()})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("update project member role")
|
||||
logger.New(ctx).WithError(err).Error("update project member role")
|
||||
return &UpdateTeamMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
role, err := r.Repository.GetRoleForTeamMember(ctx, db.GetRoleForTeamMemberParams{UserID: user.UserID, TeamID: input.TeamID})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get role for project member")
|
||||
logger.New(ctx).WithError(err).Error("get role for project member")
|
||||
return &UpdateTeamMemberRolePayload{Ok: false}, err
|
||||
}
|
||||
var url *string
|
||||
@ -871,9 +874,9 @@ func (r *notificationResolver) ID(ctx context.Context, obj *db.Notification) (uu
|
||||
}
|
||||
|
||||
func (r *notificationResolver) Entity(ctx context.Context, obj *db.Notification) (*NotificationEntity, error) {
|
||||
log.WithFields(log.Fields{"notificationID": obj.NotificationID}).Info("fetching entity for notification")
|
||||
logger.New(ctx).WithFields(log.Fields{"notificationID": obj.NotificationID}).Info("fetching entity for notification")
|
||||
entity, err := r.Repository.GetEntityForNotificationID(ctx, obj.NotificationID)
|
||||
log.WithFields(log.Fields{"entityID": entity.EntityID}).Info("fetched entity")
|
||||
logger.New(ctx).WithFields(log.Fields{"entityID": entity.EntityID}).Info("fetched entity")
|
||||
if err != nil {
|
||||
return &NotificationEntity{}, err
|
||||
}
|
||||
@ -905,7 +908,7 @@ func (r *notificationResolver) Actor(ctx context.Context, obj *db.Notification)
|
||||
if err != nil {
|
||||
return &NotificationActor{}, err
|
||||
}
|
||||
log.WithFields(log.Fields{"entityID": entity.ActorID}).Info("fetching actor")
|
||||
logger.New(ctx).WithFields(log.Fields{"entityID": entity.ActorID}).Info("fetching actor")
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, entity.ActorID)
|
||||
if err != nil {
|
||||
return &NotificationActor{}, err
|
||||
@ -935,7 +938,7 @@ func (r *projectResolver) Team(ctx context.Context, obj *db.Project) (*db.Team,
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
log.WithFields(log.Fields{"teamID": obj.TeamID, "projectID": obj.ProjectID}).WithError(err).Error("issue while getting team for project")
|
||||
logger.New(ctx).WithFields(log.Fields{"teamID": obj.TeamID, "projectID": obj.ProjectID}).WithError(err).Error("issue while getting team for project")
|
||||
return &team, err
|
||||
}
|
||||
return &team, nil
|
||||
@ -949,14 +952,14 @@ func (r *projectResolver) Members(ctx context.Context, obj *db.Project) ([]Membe
|
||||
members := []Member{}
|
||||
projectMembers, err := r.Repository.GetProjectMembersForProjectID(ctx, obj.ProjectID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get project members for project id")
|
||||
logger.New(ctx).WithError(err).Error("get project members for project id")
|
||||
return members, err
|
||||
}
|
||||
|
||||
for _, projectMember := range projectMembers {
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, projectMember.UserID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get user account by ID")
|
||||
logger.New(ctx).WithError(err).Error("get user account by ID")
|
||||
return members, err
|
||||
}
|
||||
var url *string
|
||||
@ -965,7 +968,7 @@ func (r *projectResolver) Members(ctx context.Context, obj *db.Project) ([]Membe
|
||||
}
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: user.UserID, ProjectID: obj.ProjectID})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get role for projet member by user ID")
|
||||
logger.New(ctx).WithError(err).Error("get role for projet member by user ID")
|
||||
return members, err
|
||||
}
|
||||
profileIcon := &ProfileIcon{url, &user.Initials, &user.ProfileBgColor}
|
||||
@ -1023,11 +1026,7 @@ func (r *queryResolver) FindUser(ctx context.Context, input FindUser) (*db.UserA
|
||||
}
|
||||
|
||||
func (r *queryResolver) FindProject(ctx context.Context, input FindProject) (*db.Project, error) {
|
||||
userID, role, ok := GetUser(ctx)
|
||||
log.WithFields(log.Fields{"userID": userID, "role": role}).Info("find project user")
|
||||
if !ok {
|
||||
return &db.Project{}, nil
|
||||
}
|
||||
logger.New(ctx).Info("finding project user")
|
||||
project, err := r.Repository.GetProjectByID(ctx, input.ProjectID)
|
||||
if err == sql.ErrNoRows {
|
||||
return &db.Project{}, &gqlerror.Error{
|
||||
@ -1048,10 +1047,10 @@ func (r *queryResolver) FindTask(ctx context.Context, input FindTask) (*db.Task,
|
||||
func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]db.Project, error) {
|
||||
userID, orgRole, ok := GetUser(ctx)
|
||||
if !ok {
|
||||
log.Info("user id was not found from middleware")
|
||||
logger.New(ctx).Info("user id was not found from middleware")
|
||||
return []db.Project{}, nil
|
||||
}
|
||||
log.WithFields(log.Fields{"userID": userID}).Info("fetching projects")
|
||||
logger.New(ctx).Info("fetching projects")
|
||||
|
||||
if input != nil {
|
||||
return r.Repository.GetAllProjectsForTeam(ctx, *input.TeamID)
|
||||
@ -1067,37 +1066,36 @@ func (r *queryResolver) Projects(ctx context.Context, input *ProjectsFilter) ([]
|
||||
|
||||
projects := make(map[string]db.Project)
|
||||
for _, team := range teams {
|
||||
log.WithFields(log.Fields{"teamID": team.TeamID}).Info("found team")
|
||||
logger.New(ctx).WithField("teamID", team.TeamID).Info("found team")
|
||||
teamProjects, err := r.Repository.GetAllProjectsForTeam(ctx, team.TeamID)
|
||||
if err != sql.ErrNoRows && err != nil {
|
||||
log.Info("issue getting team projects")
|
||||
return []db.Project{}, nil
|
||||
}
|
||||
for _, project := range teamProjects {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("adding team project")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("adding team project")
|
||||
projects[project.ProjectID.String()] = project
|
||||
}
|
||||
}
|
||||
|
||||
visibleProjects, err := r.Repository.GetAllVisibleProjectsForUserID(ctx, userID)
|
||||
if err != nil {
|
||||
log.WithField("userID", userID).Info("error getting visible projects for user")
|
||||
logger.New(ctx).Info("error getting visible projects for user")
|
||||
return []db.Project{}, nil
|
||||
}
|
||||
for _, project := range visibleProjects {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("found visible project")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("found visible project")
|
||||
if _, ok := projects[project.ProjectID.String()]; !ok {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("adding visible project")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("adding visible project")
|
||||
projects[project.ProjectID.String()] = project
|
||||
}
|
||||
}
|
||||
log.WithFields(log.Fields{"projectLength": len(projects)}).Info("making projects")
|
||||
logger.New(ctx).WithField("projectLength", len(projects)).Info("making projects")
|
||||
allProjects := make([]db.Project, 0, len(projects))
|
||||
for _, project := range projects {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("add project to final list")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("adding project to final list")
|
||||
allProjects = append(allProjects, project)
|
||||
}
|
||||
log.Info(allProjects)
|
||||
return allProjects, nil
|
||||
}
|
||||
|
||||
@ -1112,7 +1110,7 @@ func (r *queryResolver) FindTeam(ctx context.Context, input FindTeam) (*db.Team,
|
||||
func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) {
|
||||
userID, orgRole, ok := GetUser(ctx)
|
||||
if !ok {
|
||||
log.Error("userID or orgRole does not exist!")
|
||||
logger.New(ctx).Error("userID or org role does not exist")
|
||||
return []db.Team{}, errors.New("internal error")
|
||||
}
|
||||
if orgRole == "admin" {
|
||||
@ -1123,7 +1121,7 @@ func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) {
|
||||
teams := make(map[string]db.Team)
|
||||
adminTeams, err := r.Repository.GetTeamsForUserIDWhereAdmin(ctx, userID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("error while getting teams for user ID")
|
||||
logger.New(ctx).WithError(err).Error("error while getting teams for user ID")
|
||||
return []db.Team{}, err
|
||||
}
|
||||
|
||||
@ -1133,19 +1131,19 @@ func (r *queryResolver) Teams(ctx context.Context) ([]db.Team, error) {
|
||||
|
||||
visibleProjects, err := r.Repository.GetAllVisibleProjectsForUserID(ctx, userID)
|
||||
if err != nil {
|
||||
log.WithField("userID", userID).WithError(err).Error("error while getting visible projects for user ID")
|
||||
logger.New(ctx).WithError(err).Error("error while getting visible projects for user ID")
|
||||
return []db.Team{}, err
|
||||
}
|
||||
for _, project := range visibleProjects {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("found visible project")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("found visible project")
|
||||
if _, ok := teams[project.ProjectID.String()]; !ok {
|
||||
log.WithFields(log.Fields{"projectID": project.ProjectID.String()}).Info("adding visible project")
|
||||
logger.New(ctx).WithField("projectID", project.ProjectID).Info("adding visible project")
|
||||
team, err := r.Repository.GetTeamByID(ctx, project.TeamID)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
continue
|
||||
}
|
||||
log.WithField("teamID", project.TeamID).WithError(err).Error("error getting team by id")
|
||||
logger.New(ctx).WithField("teamID", project.TeamID).WithError(err).Error("error getting team by id")
|
||||
return []db.Team{}, err
|
||||
}
|
||||
teams[project.TeamID.String()] = team
|
||||
@ -1173,7 +1171,7 @@ func (r *queryResolver) Me(ctx context.Context) (*MePayload, error) {
|
||||
}
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, userID)
|
||||
if err == sql.ErrNoRows {
|
||||
log.WithFields(log.Fields{"userID": userID}).Warning("can not find user for me query")
|
||||
logger.New(ctx).Warning("can not find user for me query")
|
||||
return &MePayload{}, nil
|
||||
} else if err != nil {
|
||||
return &MePayload{}, err
|
||||
@ -1201,7 +1199,7 @@ func (r *queryResolver) Me(ctx context.Context) (*MePayload, error) {
|
||||
|
||||
func (r *queryResolver) Notifications(ctx context.Context) ([]db.Notification, error) {
|
||||
userID, ok := GetUserID(ctx)
|
||||
log.WithFields(log.Fields{"userID": userID}).Info("fetching notifications")
|
||||
logger.New(ctx).Info("fetching notifications")
|
||||
if !ok {
|
||||
return []db.Notification{}, errors.New("user id is missing")
|
||||
}
|
||||
@ -1215,7 +1213,7 @@ func (r *queryResolver) Notifications(ctx context.Context) ([]db.Notification, e
|
||||
}
|
||||
|
||||
func (r *queryResolver) SearchMembers(ctx context.Context, input MemberSearchFilter) ([]MemberSearchResult, error) {
|
||||
availableMembers, err := r.Repository.GetMemberData(ctx)
|
||||
availableMembers, err := r.Repository.GetMemberData(ctx, *input.ProjectID)
|
||||
if err != nil {
|
||||
return []MemberSearchResult{}, err
|
||||
}
|
||||
@ -1233,7 +1231,7 @@ func (r *queryResolver) SearchMembers(ctx context.Context, input MemberSearchFil
|
||||
memberList := map[uuid.UUID]bool{}
|
||||
for _, rank := range rankedList {
|
||||
if _, ok := memberList[masterList[rank.Target]]; !ok {
|
||||
log.WithFields(log.Fields{"source": rank.Source, "target": rank.Target}).Info("searching")
|
||||
logger.New(ctx).WithFields(log.Fields{"source": rank.Source, "target": rank.Target}).Info("searching")
|
||||
userID := masterList[rank.Target]
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, userID)
|
||||
if err != nil {
|
||||
@ -1313,7 +1311,7 @@ func (r *taskResolver) Assigned(ctx context.Context, obj *db.Task) ([]Member, er
|
||||
if err == sql.ErrNoRows {
|
||||
role = db.Role{Code: "owner", Name: "Owner"}
|
||||
} else {
|
||||
log.WithFields(log.Fields{"userID": user.UserID}).WithError(err).Error("get role for project member")
|
||||
logger.New(ctx).WithError(err).Error("get role for project member")
|
||||
return taskMembers, err
|
||||
}
|
||||
}
|
||||
@ -1407,14 +1405,14 @@ func (r *teamResolver) Members(ctx context.Context, obj *db.Team) ([]Member, err
|
||||
|
||||
teamMembers, err := r.Repository.GetTeamMembersForTeamID(ctx, obj.TeamID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get project members for project id")
|
||||
logger.New(ctx).Error("get project members for project id")
|
||||
return members, err
|
||||
}
|
||||
|
||||
for _, teamMember := range teamMembers {
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, teamMember.UserID)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get user account by ID")
|
||||
logger.New(ctx).WithError(err).Error("get user account by ID")
|
||||
return members, err
|
||||
}
|
||||
var url *string
|
||||
@ -1423,7 +1421,7 @@ func (r *teamResolver) Members(ctx context.Context, obj *db.Team) ([]Member, err
|
||||
}
|
||||
role, err := r.Repository.GetRoleForTeamMember(ctx, db.GetRoleForTeamMemberParams{UserID: user.UserID, TeamID: obj.TeamID})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("get role for projet member by user ID")
|
||||
logger.New(ctx).WithError(err).Error("get role for projet member by user ID")
|
||||
return members, err
|
||||
}
|
||||
|
||||
@ -1451,8 +1449,7 @@ func (r *userAccountResolver) ID(ctx context.Context, obj *db.UserAccount) (uuid
|
||||
func (r *userAccountResolver) Role(ctx context.Context, obj *db.UserAccount) (*db.Role, error) {
|
||||
role, err := r.Repository.GetRoleForUserID(ctx, obj.UserID)
|
||||
if err != nil {
|
||||
log.Info("beep!")
|
||||
log.WithError(err).Error("get role for user id")
|
||||
logger.New(ctx).WithError(err).Error("get role for user id")
|
||||
return &db.Role{}, err
|
||||
}
|
||||
return &db.Role{Code: role.Code, Name: role.Name}, nil
|
||||
|
@ -1,22 +1,26 @@
|
||||
extend type Mutation {
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
inviteProjectMembers(input: InviteProjectMembers!):
|
||||
InviteProjectMembersPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
input MemberInvite {
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type InviteProjectMemberPayload {
|
||||
input InviteProjectMembers {
|
||||
projectID: UUID!
|
||||
members: [MemberInvite!]!
|
||||
}
|
||||
|
||||
type InviteProjectMembersPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
projectID: UUID!
|
||||
members: [Member!]!
|
||||
}
|
||||
|
||||
input DeleteProjectMember {
|
||||
|
@ -1,89 +1,21 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
"context"
|
||||
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jordanknott/taskcafe/internal/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewStructuredLogger creates a new logger for chi router
|
||||
func NewStructuredLogger(logger *logrus.Logger) func(next http.Handler) http.Handler {
|
||||
return middleware.RequestLogger(&StructuredLogger{logger})
|
||||
// New returns a log entry with the reqID and userID fields populated if they exist
|
||||
func New(ctx context.Context) *log.Entry {
|
||||
entry := log.NewEntry(log.StandardLogger())
|
||||
if reqID, ok := ctx.Value(utils.ReqIDKey).(uuid.UUID); ok {
|
||||
entry = entry.WithField("reqID", reqID)
|
||||
}
|
||||
|
||||
// StructuredLogger is a logger for chi router
|
||||
type StructuredLogger struct {
|
||||
Logger *logrus.Logger
|
||||
if userID, ok := ctx.Value(utils.UserIDKey).(uuid.UUID); ok {
|
||||
entry = entry.WithField("userID", userID)
|
||||
}
|
||||
|
||||
// NewLogEntry creates a new log entry for the given HTTP request
|
||||
func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
|
||||
entry := &StructuredLoggerEntry{Logger: logrus.NewEntry(l.Logger)}
|
||||
logFields := logrus.Fields{}
|
||||
|
||||
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
|
||||
logFields["req_id"] = reqID
|
||||
}
|
||||
|
||||
scheme := "http"
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
logFields["http_scheme"] = scheme
|
||||
logFields["http_proto"] = r.Proto
|
||||
logFields["http_method"] = r.Method
|
||||
|
||||
logFields["remote_addr"] = r.RemoteAddr
|
||||
logFields["user_agent"] = r.UserAgent()
|
||||
|
||||
logFields["uri"] = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
|
||||
|
||||
entry.Logger = entry.Logger.WithFields(logFields)
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
// StructuredLoggerEntry is a log entry will all relevant information about a specific http request
|
||||
type StructuredLoggerEntry struct {
|
||||
Logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
// Write logs information about http request response body
|
||||
func (l *StructuredLoggerEntry) Write(status, bytes int, elapsed time.Duration) {
|
||||
l.Logger = l.Logger.WithFields(logrus.Fields{
|
||||
"resp_status": status, "resp_bytes_length": bytes,
|
||||
"resp_elapsed_ms": float64(elapsed.Nanoseconds()) / 1000000.0,
|
||||
})
|
||||
l.Logger.Debugln("request complete")
|
||||
}
|
||||
|
||||
// Panic logs if the request panics
|
||||
func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
|
||||
l.Logger = l.Logger.WithFields(logrus.Fields{
|
||||
"stack": string(stack),
|
||||
"panic": fmt.Sprintf("%+v", v),
|
||||
})
|
||||
}
|
||||
|
||||
// GetLogEntry helper function for getting log entry for request
|
||||
func GetLogEntry(r *http.Request) logrus.FieldLogger {
|
||||
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
|
||||
return entry.Logger
|
||||
}
|
||||
|
||||
// LogEntrySetField sets a key's value
|
||||
func LogEntrySetField(r *http.Request, key string, value interface{}) {
|
||||
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
||||
entry.Logger = entry.Logger.WithField(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// LogEntrySetFields sets the log entry's fields
|
||||
func LogEntrySetFields(r *http.Request, fields map[string]interface{}) {
|
||||
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
||||
entry.Logger = entry.Logger.WithFields(fields)
|
||||
}
|
||||
}
|
||||
|
89
internal/logger/route_logger.go
Normal file
89
internal/logger/route_logger.go
Normal file
@ -0,0 +1,89 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewStructuredLogger creates a new logger for chi router
|
||||
func NewStructuredLogger(logger *logrus.Logger) func(next http.Handler) http.Handler {
|
||||
return middleware.RequestLogger(&StructuredLogger{logger})
|
||||
}
|
||||
|
||||
// StructuredLogger is a logger for chi router
|
||||
type StructuredLogger struct {
|
||||
Logger *logrus.Logger
|
||||
}
|
||||
|
||||
// NewLogEntry creates a new log entry for the given HTTP request
|
||||
func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
|
||||
entry := &StructuredLoggerEntry{Logger: logrus.NewEntry(l.Logger)}
|
||||
logFields := logrus.Fields{}
|
||||
|
||||
if reqID := middleware.GetReqID(r.Context()); reqID != "" {
|
||||
logFields["req_id"] = reqID
|
||||
}
|
||||
|
||||
scheme := "http"
|
||||
if r.TLS != nil {
|
||||
scheme = "https"
|
||||
}
|
||||
logFields["http_scheme"] = scheme
|
||||
logFields["http_proto"] = r.Proto
|
||||
logFields["http_method"] = r.Method
|
||||
|
||||
logFields["remote_addr"] = r.RemoteAddr
|
||||
logFields["user_agent"] = r.UserAgent()
|
||||
|
||||
logFields["uri"] = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
|
||||
|
||||
entry.Logger = entry.Logger.WithFields(logFields)
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
// StructuredLoggerEntry is a log entry will all relevant information about a specific http request
|
||||
type StructuredLoggerEntry struct {
|
||||
Logger logrus.FieldLogger
|
||||
}
|
||||
|
||||
// Write logs information about http request response body
|
||||
func (l *StructuredLoggerEntry) Write(status, bytes int, elapsed time.Duration) {
|
||||
l.Logger = l.Logger.WithFields(logrus.Fields{
|
||||
"resp_status": status, "resp_bytes_length": bytes,
|
||||
"resp_elapsed_ms": float64(elapsed.Nanoseconds()) / 1000000.0,
|
||||
})
|
||||
l.Logger.Debugln("request complete")
|
||||
}
|
||||
|
||||
// Panic logs if the request panics
|
||||
func (l *StructuredLoggerEntry) Panic(v interface{}, stack []byte) {
|
||||
l.Logger = l.Logger.WithFields(logrus.Fields{
|
||||
"stack": string(stack),
|
||||
"panic": fmt.Sprintf("%+v", v),
|
||||
})
|
||||
}
|
||||
|
||||
// GetLogEntry helper function for getting log entry for request
|
||||
func GetLogEntry(r *http.Request) logrus.FieldLogger {
|
||||
entry := middleware.GetLogEntry(r).(*StructuredLoggerEntry)
|
||||
return entry.Logger
|
||||
}
|
||||
|
||||
// LogEntrySetField sets a key's value
|
||||
func LogEntrySetField(r *http.Request, key string, value interface{}) {
|
||||
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
||||
entry.Logger = entry.Logger.WithField(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
// LogEntrySetFields sets the log entry's fields
|
||||
func LogEntrySetFields(r *http.Request, fields map[string]interface{}) {
|
||||
if entry, ok := r.Context().Value(middleware.LogEntryCtxKey).(*StructuredLoggerEntry); ok {
|
||||
entry.Logger = entry.Logger.WithFields(fields)
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ type AuthenticationMiddleware struct {
|
||||
// Middleware returns the middleware handler
|
||||
func (m *AuthenticationMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
requestID := uuid.New()
|
||||
bearerTokenRaw := r.Header.Get("Authorization")
|
||||
splitToken := strings.Split(bearerTokenRaw, "Bearer")
|
||||
if len(splitToken) != 2 {
|
||||
@ -61,6 +62,7 @@ func (m *AuthenticationMiddleware) Middleware(next http.Handler) http.Handler {
|
||||
ctx := context.WithValue(r.Context(), utils.UserIDKey, userID)
|
||||
ctx = context.WithValue(ctx, utils.RestrictedModeKey, accessClaims.Restricted)
|
||||
ctx = context.WithValue(ctx, utils.OrgRoleKey, accessClaims.OrgRole)
|
||||
ctx = context.WithValue(ctx, utils.ReqIDKey, requestID)
|
||||
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
|
@ -6,6 +6,8 @@ type ContextKey string
|
||||
const (
|
||||
// UserIDKey is the key for the user id of the authenticated user
|
||||
UserIDKey ContextKey = "userID"
|
||||
// ReqIDKey is the unique ID key for current request
|
||||
ReqIDKey ContextKey = "reqID"
|
||||
//RestrictedModeKey is the key for whether the authenticated user only has access to install route
|
||||
RestrictedModeKey ContextKey = "restricted_mode"
|
||||
// OrgRoleKey is the key for the organization role code of the authenticated user
|
||||
|
Loading…
Reference in New Issue
Block a user