<commit_before>import keyMirror from 'keymirror';

import api from '../../../lib/api';
import {curators, managers} from './redux-modules';
import {selectUsername} from '../../../redux/session';
import {selectStudioId, setRoles, setInfo} from '../../../redux/studio';
import {withAdmin} from '../../../lib/admin-requests';

const Errors = keyMirror({
    NETWORK: null,
    SERVER: null,
    PERMISSION: null,
    DUPLICATE: null,
    USER_MUTED: null,
    UNKNOWN_USERNAME: null,
    RATE_LIMIT: null,
    MANAGER_LIMIT: null,
    UNHANDLED: null
});

const PER_PAGE_LIMIT = 24;

const normalizeError = (err, body, res) => {
    if (err) return Errors.NETWORK;
    if (res.statusCode === 400 && body.message === 'too many owners') {
        return Errors.MANAGER_LIMIT;
    }
    if (res.statusCode === 403 && body.mute_status) return Errors.USER_MUTED;
    if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION;
    if (res.statusCode === 404) return Errors.UNKNOWN_USERNAME;
    if (res.statusCode === 429) return Errors.RATE_LIMIT;
    if (res.statusCode !== 200) return Errors.SERVER;
    if (body && body.status === 'error') {
        if (body.message.indexOf('already a curator') !== -1) {
            return Errors.DUPLICATE;
        }
        return Errors.UNHANDLED;
    }
    return null;
};

const loadManagers = () => ((dispatch, getState) => {
    const state = getState();
    const studioId = selectStudioId(state);
    const managerCount = managers.selector(state).items.length;
    const opts = {
        uri: `/studios/${studioId}/managers/`,
        params: {limit: PER_PAGE_LIMIT, offset: managerCount}
    };
    api(withAdmin(opts, state), (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return dispatch(managers.actions.error(error));
        dispatch(managers.actions.append(body, body.length === PER_PAGE_LIMIT));
    });
});

const loadCurators = () => ((dispatch, getState) => {
    const state = getState();
    const studioId = selectStudioId(state);
    const curatorCount = curators.selector(state).items.length;
    const opts = {
        uri: `/studios/${studioId}/curators/`,
        params: {limit: PER_PAGE_LIMIT, offset: curatorCount}
    };
    api(withAdmin(opts, state), (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return dispatch(curators.actions.error(error));
        dispatch(curators.actions.append(body, body.length === PER_PAGE_LIMIT));
    });
});

const removeManager = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/remove/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);

        // Note `body` is undefined, this endpoint returns an html fragment
        const index = managers.selector(getState()).items
            .findIndex(v => v.username === username);
        if (index !== -1) dispatch(managers.actions.remove(index));
        // If you are removing yourself, update roles so you stop seeing the manager UI
        if (selectUsername(state) === username) {
            dispatch(setRoles({manager: false}));
        }
        dispatch(setInfo({managers: state.studio.managers - 1}));
        return resolve();
    });
}));

const removeCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/remove/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);

        // Note `body` is undefined, this endpoint returns an html fragment
        const index = curators.selector(getState()).items
            .findIndex(v => v.username === username);
        if (index !== -1) dispatch(curators.actions.remove(index));
        return resolve();
    });
}));

const inviteCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    username = username.trim();
    api({
        uri: `/site-api/users/curators-in/${studioId}/invite_curator/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        return resolve(username);
    });
}));

const promoteCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/promote/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        const curatorList = curators.selector(getState()).items;
        const index = curatorList.findIndex(v => v.username === username);
        const curatorItem = curatorList[index];
        if (index !== -1) dispatch(curators.actions.remove(index));
        dispatch(managers.actions.create(curatorItem, true));
        dispatch(setInfo({managers: state.studio.managers + 1}));
        return resolve();
    });
}));

const acceptInvitation = () => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const username = selectUsername(state);
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/add/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        api({uri: `/users/${username}`}, (userErr, userBody, userRes) => {
            const userError = normalizeError(userErr, userBody, userRes);
            if (userError) return reject(userError);
            // Note: this assumes that the user items from the curator endpoint
            // are the same structure as the single user data returned from /users/:username
            dispatch(curators.actions.create(userBody, true));
            setTimeout(() => {
                dispatch(setRoles({invited: false, curator: true}));
            }, 5 * 1000);
            return resolve();
        });
    });
}));

const transferOwnership = (newOwnerName, newOwnerId) => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    newOwnerName = newOwnerName.trim();
    api({
        uri: `/studios/${studioId}/transfer-ownership/${newOwnerName}`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        dispatch(setInfo({owner: newOwnerId}));
        return resolve();
    });
})); 

export {
    Errors,
    loadManagers,
    loadCurators,
    inviteCurator,
    acceptInvitation,
    promoteCurator,
    removeCurator,
    removeManager,
    transferOwnership
};
<commit_msg>make api request with auth<commit_after>import keyMirror from 'keymirror';

import api from '../../../lib/api';
import {curators, managers} from './redux-modules';
import {selectUsername, selectToken} from '../../../redux/session';
import {selectStudioId, setRoles, setInfo} from '../../../redux/studio';
import {withAdmin} from '../../../lib/admin-requests';

const Errors = keyMirror({
    NETWORK: null,
    SERVER: null,
    PERMISSION: null,
    DUPLICATE: null,
    USER_MUTED: null,
    UNKNOWN_USERNAME: null,
    RATE_LIMIT: null,
    MANAGER_LIMIT: null,
    UNHANDLED: null
});

const PER_PAGE_LIMIT = 24;

const normalizeError = (err, body, res) => {
    if (err) return Errors.NETWORK;
    if (res.statusCode === 400 && body.message === 'too many owners') {
        return Errors.MANAGER_LIMIT;
    }
    if (res.statusCode === 403 && body.mute_status) return Errors.USER_MUTED;
    if (res.statusCode === 401 || res.statusCode === 403) return Errors.PERMISSION;
    if (res.statusCode === 404) return Errors.UNKNOWN_USERNAME;
    if (res.statusCode === 429) return Errors.RATE_LIMIT;
    if (res.statusCode !== 200) return Errors.SERVER;
    if (body && body.status === 'error') {
        if (body.message.indexOf('already a curator') !== -1) {
            return Errors.DUPLICATE;
        }
        return Errors.UNHANDLED;
    }
    return null;
};

const loadManagers = () => ((dispatch, getState) => {
    const state = getState();
    const studioId = selectStudioId(state);
    const managerCount = managers.selector(state).items.length;
    const opts = {
        uri: `/studios/${studioId}/managers/`,
        params: {limit: PER_PAGE_LIMIT, offset: managerCount}
    };
    api(withAdmin(opts, state), (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return dispatch(managers.actions.error(error));
        dispatch(managers.actions.append(body, body.length === PER_PAGE_LIMIT));
    });
});

const loadCurators = () => ((dispatch, getState) => {
    const state = getState();
    const studioId = selectStudioId(state);
    const curatorCount = curators.selector(state).items.length;
    const opts = {
        uri: `/studios/${studioId}/curators/`,
        params: {limit: PER_PAGE_LIMIT, offset: curatorCount}
    };
    api(withAdmin(opts, state), (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return dispatch(curators.actions.error(error));
        dispatch(curators.actions.append(body, body.length === PER_PAGE_LIMIT));
    });
});

const removeManager = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/remove/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);

        // Note `body` is undefined, this endpoint returns an html fragment
        const index = managers.selector(getState()).items
            .findIndex(v => v.username === username);
        if (index !== -1) dispatch(managers.actions.remove(index));
        // If you are removing yourself, update roles so you stop seeing the manager UI
        if (selectUsername(state) === username) {
            dispatch(setRoles({manager: false}));
        }
        dispatch(setInfo({managers: state.studio.managers - 1}));
        return resolve();
    });
}));

const removeCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/remove/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);

        // Note `body` is undefined, this endpoint returns an html fragment
        const index = curators.selector(getState()).items
            .findIndex(v => v.username === username);
        if (index !== -1) dispatch(curators.actions.remove(index));
        return resolve();
    });
}));

const inviteCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    username = username.trim();
    api({
        uri: `/site-api/users/curators-in/${studioId}/invite_curator/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        return resolve(username);
    });
}));

const promoteCurator = username => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/promote/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        const curatorList = curators.selector(getState()).items;
        const index = curatorList.findIndex(v => v.username === username);
        const curatorItem = curatorList[index];
        if (index !== -1) dispatch(curators.actions.remove(index));
        dispatch(managers.actions.create(curatorItem, true));
        dispatch(setInfo({managers: state.studio.managers + 1}));
        return resolve();
    });
}));

const acceptInvitation = () => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const username = selectUsername(state);
    const studioId = selectStudioId(state);
    api({
        uri: `/site-api/users/curators-in/${studioId}/add/`,
        method: 'PUT',
        withCredentials: true,
        useCsrf: true,
        params: {usernames: username}, // sic, ?usernames=<username>
        host: '' // Not handled by the API, use existing infrastructure
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        api({uri: `/users/${username}`}, (userErr, userBody, userRes) => {
            const userError = normalizeError(userErr, userBody, userRes);
            if (userError) return reject(userError);
            // Note: this assumes that the user items from the curator endpoint
            // are the same structure as the single user data returned from /users/:username
            dispatch(curators.actions.create(userBody, true));
            setTimeout(() => {
                dispatch(setRoles({invited: false, curator: true}));
            }, 5 * 1000);
            return resolve();
        });
    });
}));

const transferOwnership = (newOwnerName, newOwnerId) => ((dispatch, getState) => new Promise((resolve, reject) => {
    const state = getState();
    const studioId = selectStudioId(state);
    const token = selectToken(state);
    newOwnerName = newOwnerName.trim();
    api({
        uri: `/studios/${studioId}/transfer-ownership/${newOwnerName}`,
        method: 'PUT',
        authentication: token,
        withCredentials: true,
        useCsrf: true
    }, (err, body, res) => {
        const error = normalizeError(err, body, res);
        if (error) return reject(error);
        dispatch(setInfo({owner: newOwnerId}));
        return resolve();
    });
})); 

export {
    Errors,
    loadManagers,
    loadCurators,
    inviteCurator,
    acceptInvitation,
    promoteCurator,
    removeCurator,
    removeManager,
    transferOwnership
};

{'fraction_non_alphanumeric': 0.14770004791566843, 'fraction_numerical': 0.004072831816003833, 'mean_word_length': 2.8008194855451856, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '125190', 'n_tokens_mistral': 4970, 'n_tokens_neox': 4904, 'n_words': 1277}