relay_server/services/projects/project/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Types that represent the current project state.
use std::sync::Arc;

use serde::{Deserialize, Serialize};

use relay_base_schema::project::ProjectKey;
use relay_quotas::Scoping;

mod info;

pub use self::info::*;

/// Representation of a project's current state.
#[derive(Clone, Debug, Default)]
pub enum ProjectState {
    /// A valid project that is not disabled.
    Enabled(Arc<ProjectInfo>),
    /// A project that was marked as "gone" by the upstream. This variant does not expose
    /// any other project information.
    Disabled,
    /// A project to which one of the following conditions apply:
    /// - The project has not yet been fetched.
    /// - The upstream returned "pending" for this project (see [`crate::services::projects::source::upstream`]).
    /// - The upstream returned an unparsable project so we have to try again.
    /// - The project has expired and must be treated as "has not been fetched".
    #[default]
    Pending,
}

impl ProjectState {
    /// Project state for an unknown but allowed project.
    ///
    /// This state is used for forwarding in Proxy mode.
    pub fn new_allowed() -> Self {
        Self::Enabled(Arc::new(ProjectInfo {
            project_id: None,
            last_change: None,
            rev: Default::default(),
            public_keys: Default::default(),
            slug: None,
            config: Default::default(),
            organization_id: None,
        }))
    }

    /// Runs a post-deserialization step to normalize the project config (e.g. legacy fields).
    pub fn sanitized(self) -> Self {
        match self {
            Self::Enabled(state) => Self::Enabled(Arc::new(state.as_ref().clone().sanitized())),
            Self::Disabled => Self::Disabled,
            Self::Pending => Self::Pending,
        }
    }

    /// Whether or not this state is pending.
    pub fn is_pending(&self) -> bool {
        matches!(self, Self::Pending)
    }

    /// Utility function that returns the project config if enabled.
    pub fn enabled(self) -> Option<Arc<ProjectInfo>> {
        match self {
            Self::Enabled(info) => Some(info),
            Self::Disabled | Self::Pending => None,
        }
    }

    /// Returns the revision of the contained project info.
    ///
    /// `None` if the revision is missing or not available.
    pub fn revision(&self) -> Revision {
        match &self {
            Self::Enabled(info) => info.rev.clone(),
            Self::Disabled | Self::Pending => Revision::default(),
        }
    }

    /// Creates `Scoping` for this project if the state is loaded.
    ///
    /// Returns `Some` if the project state has been fetched and contains a project identifier,
    /// otherwise `None`.
    pub fn scoping(&self, project_key: ProjectKey) -> Option<Scoping> {
        match self {
            Self::Enabled(info) => info.scoping(project_key),
            _ => None,
        }
    }
}

impl From<ParsedProjectState> for ProjectState {
    fn from(value: ParsedProjectState) -> Self {
        let ParsedProjectState { disabled, info } = value;
        match disabled {
            true => Self::Disabled,
            false => Self::Enabled(Arc::new(info)),
        }
    }
}

/// Project state as used in serialization / deserialization.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParsedProjectState {
    /// Whether the project state is disabled.
    #[serde(default)]
    pub disabled: bool,
    /// Project info.
    ///
    /// This contains no information when `disabled` is `true`, except for
    /// public keys in static project configs (see [`crate::services::projects::source::local`]).
    #[serde(flatten)]
    pub info: ProjectInfo,
}

/// Limited project state for external Relays.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase", remote = "ParsedProjectState")]
pub struct LimitedParsedProjectState {
    /// Whether the project state is disabled.
    pub disabled: bool,
    /// Limited project info for external Relays.
    ///
    /// This contains no information when `disabled` is `true`, except for
    /// public keys in static project configs (see [`crate::services::projects::source::local`]).
    #[serde(with = "LimitedProjectInfo")]
    #[serde(flatten)]
    pub info: ProjectInfo,
}